async_tick/
sleep.rs

1use super::waiter::{Token, Waiter};
2use super::{now, WAITS, WAITS_NUM};
3use core::future::Future;
4use core::pin::Pin;
5use core::task::{Context, Poll};
6use core::time::Duration;
7
8pub fn sleep(duration: Duration) -> Sleep {
9    let deadline = now() + duration.as_nanos() as u64;
10    Sleep {
11        pool: &WAITS,
12        deadline,
13        token: None,
14    }
15}
16pub fn sleep_until(deadline: u64) -> Sleep {
17    Sleep {
18        pool: &WAITS,
19        deadline,
20        token: None,
21    }
22}
23
24pub struct Sleep {
25    pool: &'static Waiter<WAITS_NUM>,
26    deadline: u64,
27    token: Option<Token<'static, WAITS_NUM>>,
28}
29impl Future for Sleep {
30    type Output = ();
31    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
32        let deadline = self.deadline;
33        if deadline < now() {
34            return Poll::Ready(());
35        }
36        let waker = cx.waker();
37        if let Some(token) = &self.token {
38            token.swap(waker.clone(), deadline);
39        } else if let Ok(token) = self.pool.register() {
40            token.swap(waker.clone(), deadline);
41            self.token = Some(token);
42        } else {
43            waker.wake_by_ref();
44        }
45        if deadline < now() {
46            Poll::Ready(())
47        } else {
48            Poll::Pending
49        }
50    }
51}