Noodles for every philosopher
This commit is contained in:
commit
0984849288
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
/target
|
7
Cargo.lock
generated
Normal file
7
Cargo.lock
generated
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
version = 3
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "philosophy"
|
||||||
|
version = "0.1.0"
|
8
Cargo.toml
Normal file
8
Cargo.toml
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
[package]
|
||||||
|
name = "philosophy"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
116
src/main.rs
Normal file
116
src/main.rs
Normal file
|
@ -0,0 +1,116 @@
|
||||||
|
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
|
||||||
|
}
|
Loading…
Reference in a new issue