summaryrefslogtreecommitdiff
path: root/examples/dining_philosophers.rs
blob: f8657df81a4fc53581895a71302fecab855574f5 (plain)
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::lock().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();
	}
}