I have the following (simplified) code that spawns a few threads that do long and complex operations to build a Transactions struct. This Transactions struct contains fields with Rc. At the end of the threads I want to return the computed Transactions struct to the calling thread through an mpsc::channel.
use std::thread;
use std::collections::HashMap;
use std::sync::mpsc::{channel, Sender};
use std::rc::Rc;
#[derive(Debug)]
struct Transaction {
id: String,
}
#[derive(Debug)]
struct Transactions {
list: Vec<Rc<Transaction>>,
index: HashMap<String, Rc<Transaction>>,
}
fn main() {
let (tx, rx) = channel();
for _ in 0..4 {
tx = Sender::clone(&tx);
thread::spawn(move || {
// complex and long computation to build a Transactions struct
let transactions = Transactions { list: Vec::new(), index: HashMap::new() };
tx.send(transactions).unwrap();
});
}
drop(tx);
for transactions in rx {
println!("Got: {:?}", transactions);
}
}
The compiler complains that std::rc::Rc<Transaction> cannot be sent safely between threads because it does not implement the std::marker::Send trait.
error[E0277]: `std::rc::Rc<Transaction>` cannot be sent between threads safely
--> src/main.rs:23:5
|
23 | thread::spawn(move || {
| ^^^^^^^^^^^^^ `std::rc::Rc<Transaction>` cannot be sent between threads safely
|
= help: the trait `std::marker::Send` is not implemented for `std::rc::Rc<Transaction>`
= note: required because of the requirements on the impl of `std::marker::Send` for `std::ptr::Unique<std::rc::Rc<Transaction>>`
= note: required because it appears within the type `alloc::raw_vec::RawVec<std::rc::Rc<Transaction>>`
= note: required because it appears within the type `std::vec::Vec<std::rc::Rc<Transaction>>`
= note: required because it appears within the type `Transactions`
= note: required because of the requirements on the impl of `std::marker::Send` for `std::sync::mpsc::Sender<Transactions>`
= note: required because it appears within the type `[closure@src/main.rs:23:19: 27:6 tx:std::sync::mpsc::Sender<Transactions>]`
I understand the I could replace Rc by Arc, but was looking to know if there was any other solution to avoid the performance penalty of using Arc, because the Rc structs are never accessed by two threads at the same time.
Rcis for within threads,Arcis for between threads.