use std::{thread, time::Duration};
use happylock::{collection, ThreadKey};
type Mutex<T> = happylock::mutex::Mutex<T, sys_locks::Mutex>;
static PHILOSOPHERS: [Philosopher; 5] = [
Philosopher {
name: "Socrates",
left: 0,
right: 1,
},
Philosopher {
name: "John Rawls",
left: 1,
right: 2,
},
Philosopher {
name: "Jeremy Bentham",
left: 2,
right: 3,
},
Philosopher {
name: "John Stuart Mill",
left: 3,
right: 4,
},
Philosopher {
name: "Judith Butler",
left: 4,
right: 0,
},
];
static FORKS: [Mutex<()>; 5] = [
Mutex::new(()),
Mutex::new(()),
Mutex::new(()),
Mutex::new(()),
Mutex::new(()),
];
struct Philosopher {
name: &'static str,
left: usize,
right: usize,
}
impl Philosopher {
fn cycle(&self) {
let key = ThreadKey::get().unwrap();
thread::sleep(Duration::from_secs(1));
// safety: no philosopher asks for the same fork twice
let forks = [&FORKS[self.left], &FORKS[self.right]];
let forks = unsafe { collection::RefLockCollection::new_unchecked(&forks) };
let forks = forks.lock(key);
println!("{} is eating...", self.name);
thread::sleep(Duration::from_secs(1));
println!("{} is done eating", self.name);
drop(forks);
}
}
fn main() {
let handles: Vec<_> = PHILOSOPHERS
.iter()
.map(|philosopher| thread::spawn(move || philosopher.cycle()))
// The `collect` is absolutely necessary, because we're using lazy
// iterators. If `collect` isn't used, then the thread won't spawn
// until we try to join on it.
.collect();
for handle in handles {
_ = handle.join();
}
}
|