Skip to content

Commit ef401dc

Browse files
committed
tmp: Hand semaphore version
1 parent 32c2620 commit ef401dc

File tree

2 files changed

+97
-0
lines changed

2 files changed

+97
-0
lines changed
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
//! Hand-written semaphore solution
2+
//!
3+
//! Implements the semaphore solution to the dining philosopher problem, but with all Futures
4+
//! written by hand.
5+
//!
6+
//! For this particular case, we will use Arc with the Semaphores instead of Rc, and not try to be
7+
//! thread-local.
8+
9+
use core::{future::Future, task::Poll};
10+
11+
use alloc::vec::Vec;
12+
use zephyr::{kio::{spawn, sync::Mutex}, sync::Arc, sys::sync::Semaphore, work::{futures::JoinHandle, WorkQueue}};
13+
14+
use crate::{Stats, NUM_PHIL};
15+
16+
/// Number of iterations for each philospher.
17+
const EAT_COUNT: usize = 10;
18+
19+
pub fn phil(wqueue: &WorkQueue) -> impl Future<Output = Arc<Mutex<Stats>>> + Send {
20+
let stats = Arc::new(Mutex::new(Stats::default()));
21+
22+
// One fork for each philospher.
23+
let forks: Vec<_> = (0..NUM_PHIL)
24+
.map(|_| Arc::new(Semaphore::new(1, 1).unwrap()))
25+
.collect();
26+
27+
// Create all of the philosphers.
28+
let phils: Vec<_> = (0..NUM_PHIL)
29+
.map(|i| {
30+
// Determine the two forks.
31+
let forks = if i == NUM_PHIL - 1 {
32+
[forks[0].clone(), forks[i].clone()]
33+
} else {
34+
[forks[i].clone(), forks[i + 1].clone()]
35+
};
36+
37+
spawn(one_phil(forks, i, stats.clone()), wqueue, c"phil")
38+
})
39+
.collect();
40+
41+
Phil {
42+
stats, phils,
43+
}
44+
}
45+
46+
struct Phil<F>
47+
where
48+
F: Future<Output = ()> + Send,
49+
{
50+
stats: Arc<Mutex<Stats>>,
51+
phils: Vec<JoinHandle<F>>,
52+
}
53+
54+
impl<F> Future for Phil<F>
55+
where
56+
F: Future<Output = ()> + Send,
57+
{
58+
type Output = Arc<Mutex<Stats>>;
59+
60+
fn poll(self: core::pin::Pin<&mut Self>, cx: &mut core::task::Context<'_>) -> core::task::Poll<Self::Output> {
61+
if self.phils.is_empty() {
62+
return Poll::Ready(self.stats.clone());
63+
}
64+
let _ = cx;
65+
todo!()
66+
}
67+
}
68+
69+
/// Simulate a single philospher
70+
fn one_phil(forks: [Arc<Semaphore>; 2], n: usize, stats: Arc<Mutex<Stats>>) -> impl Future<Output = ()> + Send {
71+
OnePhil {
72+
forks, n, stats,
73+
}
74+
}
75+
76+
struct OnePhil {
77+
forks: [Arc<Semaphore>; 2],
78+
n: usize,
79+
stats: Arc<Mutex<Stats>>,
80+
}
81+
82+
impl Future for OnePhil {
83+
type Output = ();
84+
85+
fn poll(self: core::pin::Pin<&mut Self>, cx: &mut core::task::Context<'_>) -> core::task::Poll<Self::Output> {
86+
let _ = cx;
87+
todo!()
88+
}
89+
}

samples/work-philosophers/src/lib.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ use zephyr::{
1919
};
2020

2121
mod async_sem;
22+
mod hand_sem;
2223

2324
/// How many philosophers. There will be the same number of forks.
2425
const NUM_PHIL: usize = 6;
@@ -57,6 +58,13 @@ extern "C" fn rust_main() {
5758
let _ = Arc::into_raw(lower_worker.clone());
5859
let _ = Arc::into_raw(worker.clone());
5960

61+
// Run the hand-written semaphore one.
62+
printkln!("Running 'hand-sem' test");
63+
let handle = spawn(hand_sem::phil(&worker), &worker, c"hand-sem");
64+
let stats = handle.join();
65+
printkln!("Done with hand-sem test");
66+
stats.show();
67+
6068
// First run the async semaphore based one.
6169
printkln!("Running 'async-sem' test");
6270
let handle = spawn(async_sem::phil(), &worker, c"async-sem");

0 commit comments

Comments
 (0)