# Using Message Passing to Transfer Data between Threads `Message Passing` on thread/actor send messages containing data - "Share memory by communicating, not communicating by sharing data." `channel` - Implmentation of communicating service. 1 Transmitter and 1 Receiver. Transmitter sends, receiver gets. If one is dropped, the channel is dropped. ```rust use std::sync::mpsc; // Multiple Producer, Single Consumer fn channel_test() { // Generate transmitter-receiver pair in a tuple // Use let (tuple) to destructure into 2 variables! let (tx,rx) = mpsc::channel(); // By itself, this does not compile // We send the transmitter into another thread thread::spawn(move || { let val = String::from("Hi from spawned!"); tx.send(val).unwrap(); // send(...) return `Result` if the receiver is dropped, returns error }); let received = rx.recv().unwrap(); println!("Got message: {}", received); } ``` `recv()` blocks the thread until it receives something, returning a `Result`. If the transmitter were to be dropped, it would return error. `try_recv()` does not block and returns an immediate `Result`, with `Err` if there are no messages to receive. ## Channels and Ownership transfer `send()` can transfer ownership of values from transmitter to receiver, a value that has been sent will no longer be accessible: ```rust thread::spawn(move || { let val = String::from("hi"); tx.send(val).unwrap(); println!("val is {}", val); // Illegal, main has val, not spawned }); ``` ## Sending Multiple Values and check on the Receiver ```rust thread::spawn(move || { let vals = vec![ String::from("hi"), String::from("from"), String::from("the"), String::from("thread"), ]; for val in vals { tx.send(val).unwrap(); thread::sleep(Duration::from_secs(1)); } }); for received in rx { println!("Got: {}", received); } ``` The iterator `foreach` will now become like a for loop waiting on `recv()`, each time a new message is sent, an iteration takes place in main. ### Multiple Producers - Cloning the Transmitter We can actually just `clone()` the transmitter and send that clone to another thread. The receive will receive from both without issues. ```rust let tx1 = tx.clone(); thread::spawn(move || { let vals = vec![ String::from("more"), String::from("messages"), String::from("for"), String::from("you"), ]; for val in vals { tx.send(val).unwrap(); thread::sleep(Duration::from_secs(1)); } }); ``` Here we spawn another thread sending more messages at the same time. Remeber that ordering is a non-guarantee when receiving form multiple sources, we can't know exactly execution times, process prioritazion,... Have to be careful!