117 lines
2.9 KiB
Rust
117 lines
2.9 KiB
Rust
use std::sync::{Arc, Mutex};
|
|
|
|
async fn eat(philosopher: usize, ForkId(first): ForkId, ForkId(second): ForkId) {
|
|
for _ in 0..3 {
|
|
println!(
|
|
"Philosopher {}: I'm eating with forks {} and {}",
|
|
philosopher, first, second
|
|
);
|
|
yield_now().await;
|
|
}
|
|
}
|
|
|
|
fn philosopher(
|
|
id: usize,
|
|
first: Arc<Mutex<ForkId>>,
|
|
second: Arc<Mutex<ForkId>>,
|
|
) -> std::pin::Pin<Box<dyn std::future::Future<Output = ()>>> {
|
|
Box::pin(async move {
|
|
loop {
|
|
if let Ok(first_guard) = first.try_lock() {
|
|
println!("Philosopher {}: got first guard", id);
|
|
yield_now().await;
|
|
if let Ok(second_guard) = second.try_lock() {
|
|
eat(id, *first_guard, *second_guard).await;
|
|
|
|
drop(second_guard);
|
|
drop(first_guard);
|
|
break;
|
|
}
|
|
println!("Philosopher {}: did not get second guard", id);
|
|
yield_now().await;
|
|
drop(first_guard);
|
|
continue;
|
|
}
|
|
println!("Philosopher {}: did not get first guard", id);
|
|
yield_now().await;
|
|
}
|
|
})
|
|
}
|
|
|
|
fn philosophy(num_philosophers: usize) {
|
|
let mut mutexes = Vec::new();
|
|
for i in 0..num_philosophers {
|
|
mutexes.push(Arc::new(Mutex::new(ForkId(i))));
|
|
}
|
|
|
|
let mut futures = Vec::new();
|
|
for i in 0..num_philosophers {
|
|
let next_index = (i + 1) % num_philosophers;
|
|
|
|
let [first_index, second_index] = if (i % 2) == 0 {
|
|
[i, next_index]
|
|
} else {
|
|
[next_index, i]
|
|
};
|
|
|
|
let first = Arc::clone(&mutexes[first_index]);
|
|
let second = Arc::clone(&mutexes[second_index]);
|
|
|
|
futures.push(philosopher(i, first, second));
|
|
}
|
|
|
|
let waker = Arc::new(DummyWaker).into();
|
|
let mut context = std::task::Context::from_waker(&waker);
|
|
|
|
for iteration in 0.. {
|
|
println!("state at {}:", iteration);
|
|
futures = futures.drain(..).filter_map(|mut future| {
|
|
if future.as_mut().poll(&mut context).is_ready() {
|
|
None
|
|
} else {
|
|
Some(future)
|
|
}
|
|
}).collect();
|
|
|
|
if futures.is_empty() {
|
|
break;
|
|
}
|
|
}
|
|
|
|
println!("Hello, world!");
|
|
}
|
|
|
|
fn main() {
|
|
philosophy(4096);
|
|
}
|
|
|
|
#[derive(Clone, Copy)]
|
|
struct ForkId(usize);
|
|
|
|
struct YieldNow(Option<()>);
|
|
|
|
struct DummyWaker;
|
|
impl std::task::Wake for DummyWaker {
|
|
fn wake(self: Arc<Self>) {}
|
|
fn wake_by_ref(self: &Arc<Self>) {}
|
|
}
|
|
|
|
impl std::future::Future for YieldNow {
|
|
type Output = ();
|
|
|
|
fn poll(
|
|
mut self: std::pin::Pin<&mut Self>,
|
|
_: &mut std::task::Context<'_>,
|
|
) -> std::task::Poll<Self::Output> {
|
|
if let Some(()) = self.as_mut().0.take() {
|
|
std::task::Poll::Pending
|
|
} else {
|
|
std::task::Poll::Ready(())
|
|
}
|
|
}
|
|
}
|
|
|
|
async fn yield_now() {
|
|
YieldNow(Some(())).await
|
|
}
|