Skip to content

Instantly share code, notes, and snippets.

@khanhtc1202
Created November 5, 2019 03:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save khanhtc1202/261e6a48c4f6fae517914915590d3c09 to your computer and use it in GitHub Desktop.
Save khanhtc1202/261e6a48c4f6fae517914915590d3c09 to your computer and use it in GitHub Desktop.
Dining Philosopher
use std::sync::{Arc, Mutex};
use std::thread;
use std::time::Duration;
struct Philosopher {
id: usize,
left: Arc<Mutex<Chopstick>>,
right: Arc<Mutex<Chopstick>>,
}
impl Philosopher {
fn new(id: usize, left: Arc<Mutex<Chopstick>>, right: Arc<Mutex<Chopstick>>) -> Self {
Philosopher { id, left, right }
}
fn think(&self) {
println!("Philosopher {}: Thinking...", self.id);
thread::sleep(Duration::from_secs(2));
}
fn eat(&self) {
let mut left_cs = if let Ok(chopstick) = self.left.try_lock() {
chopstick
} else {
println!("Philosopher {}: OOPS! Left chopstick not available. Waiting...", self.id);
self.left.lock().unwrap()
};
left_cs.get(self);
let mut right_cs = if let Ok(chopstick) = self.right.try_lock() {
chopstick
} else {
println!("Philosopher {}: OOPS! Right chopstick not available. Waiting...", self.id);
self.right.lock().unwrap()
};
right_cs.get(self);
println!("Philosopher {}: Eating...", self.id);
thread::sleep(Duration::from_secs(4));
right_cs.put(self);
left_cs.put(self);
}
}
struct Chopstick {
id: usize,
by: Option<usize>,
}
impl Chopstick {
fn new(n: usize) -> Self {
Chopstick {
id: n,
by: None,
}
}
fn get(&mut self, p: &Philosopher) {
if self.by != None {
panic!(); // Invalid state. Since chopstick should not belong to anyone when a philosopher gets it
}
println!("Chopstick {}: Picked up by Philosopher {}", self.id, p.id);
self.by = Some(p.id);
}
fn put(&mut self, p: &Philosopher) {
if self.by != Some(p.id) {
panic!(); // Invalid state. Since chopstick should belong to philosopher who trying to put it back
}
println!("Chopstick {}: Released by Philosopher {}", self.id, p.id);
self.by = None;
}
}
fn deploy(n: usize, for_left: Arc<Mutex<Chopstick>>, for_right: Arc<Mutex<Chopstick>>) -> thread::JoinHandle<()> {
thread::spawn(move || {
let ph = Philosopher::new(n, for_left, for_right);
loop {
ph.think();
ph.eat();
}
})
}
fn main() {
let cs1 = Arc::new(Mutex::new(Chopstick::new(1)));
let cs2 = Arc::new(Mutex::new(Chopstick::new(2)));
let cs3 = Arc::new(Mutex::new(Chopstick::new(3)));
let cs4 = Arc::new(Mutex::new(Chopstick::new(4)));
let cs5 = Arc::new(Mutex::new(Chopstick::new(5)));
let mut handles = vec![];
handles.push(deploy(1, cs1.clone(), cs2.clone()));
handles.push(deploy(2, cs2.clone(), cs3.clone()));
handles.push(deploy(3, cs3.clone(), cs4.clone()));
handles.push(deploy(4, cs4.clone(), cs5.clone()));
handles.push(deploy(5, cs5.clone(), cs1.clone()));
for handle in handles {
let _ = handle.join();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment