use std::thread::{spawn, sleep_ms}; use std::sync::mpsc::channel; fn main() { // Names of attendees. let names = vec![format!("A"), format!("B"), format!("C"), format!("D"), format!("E")]; // Create a channel to communicate between attendees and the toaster. let (toaster_tx, toaster_rx) = channel(); // Iterate over attendees. for name in names.into_iter() { // Create a channel to send a bagel down. let (tx, rx) = channel(); // Clone the toaster channel's transmitter (multiple sender, single receiver) // so each attendee can send bagels. let toaster_tx = toaster_tx.clone(); // Spawn a thread for each attendee. spawn(move || { // Create an attendee. let mut a = Attendee::new(name); // Receive a bagel. let bagel = rx.recv().unwrap(); // Create a channel to receiver the bagel back from the toaster. let (ack, rx1) = channel(); // Send the bagel to the toaster along with a way to get it back. toaster_tx.send((bagel, ack)).unwrap(); // Receive the bagel back from the toaster. let toasted_bagel = rx1.recv().unwrap(); // Pick up the bagel and eat it. a.pick_up_bagel(toasted_bagel); a.eat_breakfast(); }); // Send a bagel to the attendee. tx.send(Bagel::Raisin).unwrap(); } // Start the toaster thread. spawn(move || { // For each message coming from the toaster... for (mut bagel, ack) in toaster_rx { // We get a bagel and one end of a channel. println!("Toasting {:?}", bagel); // Toast the bagel. bagel.toast(); println!("Toasted {:?}", bagel); // And send it back. ack.send(bagel).unwrap(); } }); // Give all the attendees time to toast their bagels. sleep_ms(1000); } struct Attendee { name: String, breakfast: Option, } #[derive(Debug)] enum Bagel { Plain(BagelColour), Raisin, } #[derive(Debug)] enum BagelColour { PaleBrown, DarkBrown, } impl Attendee { fn new(name: String) -> Attendee { Attendee { name: name, breakfast: None, } } fn pick_up_bagel(&mut self, bagel: Bagel) { self.breakfast = Some(bagel); } fn eat_breakfast(&mut self) { match self.breakfast { Some(_) => { self.breakfast = None; println!("Yum! ({})", self.name); } None => println!("I don't have any breakfast :-( ({})", self.name) } } } impl Bagel { fn toast(&mut self) { sleep_ms(10); match *self { Bagel::Plain(ref mut c) => { *c = BagelColour::DarkBrown; } _ => {} } } }