|
|
@@ -0,0 +1,108 @@ |
|
|
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... |
|
|
while let Ok((mut bagel, ack)) = toaster_rx.recv() { |
|
|
// 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<Bagel>, |
|
|
} |
|
|
|
|
|
#[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; |
|
|
} |
|
|
_ => {} |
|
|
} |
|
|
} |
|
|
} |