Skip to main content

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
16const MAX_POLL_INTERVAL: Duration = Duration::from_millis(20);
17
18impl<T> StackRunner<T>
19where
20    T: Device,
21{
22    pub fn new(stack: Stack, device: T, wake_signal: WakeSignal) -> Self {
23        Self {
24            stack,
25            device,
26            wake_signal,
27        }
28    }
29
30    pub async fn run(&mut self) -> ! {
31        loop {
32            let next_poll_in = self
33                .stack
34                .with_mutable_no_wake(|stack_inner| {
35                    if stack_inner.enabled {
36                        stack_inner.poll(&mut self.device)
37                    } else {
38                        None
39                    }
40                })
41                .await;
42
43            let sleep_duration = match next_poll_in {
44                Some(d) if d.is_zero() => {
45                    embassy_futures::yield_now().await;
46                    continue;
47                }
48                Some(d) => d.min(MAX_POLL_INTERVAL),
49                None => MAX_POLL_INTERVAL,
50            };
51
52            select(task::sleep(sleep_duration), self.wake_signal.wait()).await;
53        }
54    }
55}