pub fn new(producer: &Read, consumer: &Write, name: String) {
let (tx, rx) = mpsc::channel();
let read_wrapper = Arc::new(Mutex::new(producer));
let x = read_wrapper.clone();
let tx_thread = try!(
Builder::new()
.name(format!("Send thread: {}", name))
.scoped(move || tx_thread_main(tx, x)));
}
Still the same problems:
error: the trait `core::marker::Sync` is not implemented for the type `std::io::Read` [E0277]
note: `std::io::Read` cannot be shared between threads safely
Although I am NOT trying to share std::io::Read between threads but a Arc on a Mutex on a Reference on it.
To send Arc's across threads, Arc<T> needs to implement Send. To implement Send, Arc<T> requires that T implement Send and Sync. In your case, T is a Mutex<V>. For Mutex<V> to implement Send + Sync, V needs to implement Send. However, &Read doesn't implement Send.
To fix this, use &(Read + Sync) because &Sync implements Send. We need the type to be Sync because we are trying to share it across threads (&T is not an exclusive reference). However, you probably want &mut Read so you'll actually need &mut (Read + Send) because &mut Send implements Send. &mut Send can implement Send because &mut T is an exclusive reference.
For more information, read the Arc, Mutex, Send, and Sync API docs (specifically, the implementors section).
To put the Read in a Mutex<&'a mut (Read + Send)> I need a Read + Send before. How can I do that? Sadly neither the specification nor the Rust Programming Book specify how to do that.
First thing is I don't understand what the Generics syntax Read + Send is (means) and how such a type/variable could be created.
Second I don't understand how I can "box" a Read somehow that it is guaranteed to be thread-safe and can be Send. I think it is ok that Read implementations usually aren't Send.
&Trait or Box<Trait> are trait objects (this isn't generic programming BTW, because it involves dynamic dispatch). Trait Objects.
Since a trait only describes a subset of the object's behavior, you can combine them so a Box<Read + Send> is a trait object that implements both Read and Send.
If I understand you correctly I can now specify the type Read + Send in a function header. I can call this function with parameters like std::fs::File or std::process::ChildStdin
I don't know the rationale to not make Read a Send, but that doesn't matter right now.
Yes, but also often you would do it in a generic way:
pub fn new<R: Read + Send, W: Write + Send>(
producer: R, // a &Read (as opposed to &mut Read) is useless and you most likely want to take ownership of the reader
consumer: W, // ditto
name: &str) // if you're only going to pass the name to format, no need to own it
-> YourStruct {
...
[quote="YBRyn, post:12, topic:1678"]
I don't know the rationale to not make Read a Send, but that doesn't matter right now.
[/quote]Some Read-able types aren't Send-able.