network/manager/
runner.rs

1use crate::manager::stack::Stack;
2use core::time::Duration;
3use embassy_futures::select::select;
4use smoltcp::phy::Device;
5use synchronization::{Arc, blocking_mutex::raw::CriticalSectionRawMutex, signal::Signal};
6
7/// A signal used to wake the runner when socket activity occurs.
8pub type WakeSignal = Arc<Signal<CriticalSectionRawMutex, ()>>;
9
10pub struct StackRunner<T> {
11    stack: Stack,
12    device: T,
13    wake_signal: WakeSignal,
14}
15
16impl<T> StackRunner<T>
17where
18    T: Device,
19{
20    pub fn new(stack: Stack, device: T, wake_signal: WakeSignal) -> Self {
21        Self {
22            stack,
23            device,
24            wake_signal,
25        }
26    }
27
28    pub async fn run(&mut self) -> ! {
29        loop {
30            let next_poll_in = self
31                .stack
32                .with_mutable_no_wake(|stack_inner| {
33                    if stack_inner.enabled {
34                        stack_inner.poll(&mut self.device)
35                    } else {
36                        None
37                    }
38                })
39                .await;
40
41            let sleep_duration = match next_poll_in {
42                Some(d) if d.is_zero() => {
43                    embassy_futures::yield_now().await;
44                    continue;
45                }
46                Some(d) => d,
47                None => Duration::from_millis(200),
48            };
49
50            select(task::sleep(sleep_duration), self.wake_signal.wait()).await;
51        }
52    }
53}