1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
use std::{thread, time::Duration};

use happylock::{LockCollection, Mutex, ThreadKey};

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 =
			unsafe { LockCollection::new_unchecked([&FORKS[self.left], &FORKS[self.right]]) };
		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 = PHILOSOPHERS
		.iter()
		.map(|philosopher| thread::spawn(move || philosopher.cycle()));

	for handle in handles {
		_ = handle.join();
	}
}