|
| 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 | +} |
0 commit comments