use std::sync::mpsc::{self, Sender, Receiver}; use std::thread; use std::time::Duration; use rand::Rng; fn main() { main_1_1(); } // simple example of messages in Rust // One thread sends message back to main, once fn main_1_1() { // set up the messaging "channel" let (tx, rx) = mpsc::channel(); // create thread move because needed to take ownership of tx let handle = thread::spawn(move || { let val = String::from("hi"); tx.send(val).unwrap(); thread::sleep(Duration::from_millis(1)); }); // wait for message // this blocks!!! let received = rx.recv().unwrap(); println!("Got: {}", received); // because thread last thing is to send message, and main blocks until message received // this is fairly unnecessary; but it never hurts println!("Waiting 1_1"); handle.join().unwrap(); } fn main_1_10() { // set up the messaging "channel" let (tx, rx) = mpsc::channel(); // create thread move needed to take ownership of tx let handle = thread::spawn(move || { let number = 10 + rand::thread_rng().gen_range(1..=100); for i in 1..number { let val = format!("hi {i}"); tx.send(val).unwrap(); thread::sleep(Duration::from_millis(1)); } }); // wait for messages for received in rx { println!("Got: {}", received); } println!("Waiting 1_10"); // how does rust know that producer is done?? handle.join().unwrap(); } fn main_10_10() { // set up the messaging "channel" // "mp" is Multiple Producer let (tx, rx) = mpsc::channel(); let mut handles = vec![]; // create thread move needed to take ownership of tx for j in 1..10 { let ty = tx.clone(); handles.push(thread::spawn(move || { let number = rand::thread_rng().gen_range(10..=100); for i in 1..number { let val = format!("hi {j} {i}"); ty.send(val).unwrap(); thread::sleep(Duration::from_millis(1)); } ty.send("END".to_string()).unwrap(); })); } // wait for messages // when you have cloned the sender, the channel does not close so this loop does not end // so added an END message and a countdown So I roll my own "wait group" counter taking inspiration from go // there should be a better way!!! maybe loop through handles asking "is_finished()"? This would also // mean that thread does not need to send "end" message let mut end_count = 9; for received in rx { println!("Got: {}", received); if received=="END" { end_count -= 1; } if end_count==0 { break; } } println!("Waiting 10_10"); for h in handles{ h.join().unwrap(); } } // here the threads keep sending messages to the main until the main says to stop // to do this, we need the main to have a sending channel to the thread // in addition to the thread having a sending channel to the main. fn main_2d() { // set up the messaging "channel" for thread to main // "mp" is Multiple Producer let threads = 5; let (tx, rx) = mpsc::channel(); let mut handles = vec![]; let mut out_channels = vec![]; // create thread move needed to take ownership of tx for j in 0..threads { let ty = tx.clone(); let (itx, irx) = mpsc::channel(); out_channels.push(itx); handles.push(thread::spawn(move || { loop { thread::sleep(Duration::from_millis(1)); let val = format!("hi {j}"); ty.send((j, val)).unwrap(); let keep_going:bool = irx.recv().unwrap(); if !keep_going { break; } } })); } // wait for messages // respond to message with a "send another" or "stop" let mut end_count = threads; let mut message_count = 0; let message_max = 100 + rand::thread_rng().gen_range(1..=100); for (idx, received) in rx { message_count += 1; if message_count >= message_max { end_count -= 1; out_channels[idx].send(false).unwrap(); } else { out_channels[idx].send(true).unwrap(); } println!("Got: {} {} {}", received, end_count, message_count); if end_count == 0 { break; } } println!("Waiting to exhale"); for h in handles{ h.join().unwrap(); } }