async_hal/delay/
mod.rs

1use core::{
2    pin::Pin,
3    task::{Context, Poll},
4};
5use futures::{Future, FutureExt, Stream};
6
7pub use embedded_hal::timer::Periodic;
8
9mod ready;
10pub use ready::{ready, AlreadyStarted, Ready};
11
12#[cfg(feature = "nb")]
13mod timer;
14#[cfg(feature = "nb")]
15pub use timer::Timer;
16
17pub trait DelayMs {
18    /// The type of duration to delay for.
19    type Delay;
20
21    /// The error returned on failure.
22    type Error;
23
24    /// Start a new delay.
25    fn start(&mut self, ms: Self::Delay) -> Result<(), Self::Error>;
26
27    /// Poll a delay of `ms` milliseconds.
28    /// This function may wake the calling function rather than the waker.
29    fn poll_delay_ms(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Result<(), Self::Error>>;
30
31    /// Attempt to cancel a delay in progress.
32    fn cancel(&mut self) -> Result<(), Self::Error>;
33
34    fn poll_delay_ms_unpin(&mut self, cx: &mut Context) -> Poll<Result<(), Self::Error>>
35    where
36        Self: Unpin,
37    {
38        Pin::new(self).poll_delay_ms(cx)
39    }
40
41    /// Delay for `ms` milliseconds.
42    /// Starts a new delay and returns a [`Future`] that completes when either the timer expires.
43    /// The returned future also implements [`Stream`] if this delay is [`Periodic`].
44    ///
45    /// When dropped, this future will attempt to cancel the current delay.
46    fn delay_ms(&mut self, ms: Self::Delay) -> DelayMsFuture<Self>
47    where
48        Self: Unpin,
49    {
50        DelayMsFuture {
51            timer: self,
52            ms: Some(ms),
53            is_started: false,
54        }
55    }
56}
57
58pub struct DelayMsFuture<'a, T: ?Sized + DelayMs> {
59    timer: &'a mut T,
60    ms: Option<T::Delay>,
61    is_started: bool,
62}
63
64impl<T> Future for DelayMsFuture<'_, T>
65where
66    T: ?Sized + DelayMs + Unpin,
67    T::Delay: Unpin,
68{
69    type Output = Result<(), T::Error>;
70
71    fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
72        if !self.is_started {
73            let ms = self.ms.take().unwrap();
74            self.timer.start(ms)?;
75
76            self.is_started = true;
77        }
78
79        self.timer.poll_delay_ms_unpin(cx)
80    }
81}
82
83impl<T> Stream for DelayMsFuture<'_, T>
84where
85    T: ?Sized + Periodic + DelayMs + Unpin,
86    T::Delay: Unpin,
87{
88    type Item = Result<(), T::Error>;
89
90    fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<Self::Item>> {
91        self.poll_unpin(cx).map(Some)
92    }
93}
94
95impl<T> Drop for DelayMsFuture<'_, T>
96where
97    T: ?Sized + DelayMs,
98{
99    fn drop(&mut self) {
100        self.timer.cancel().ok();
101    }
102}