Skip to main content

dope_fiber/task/time/
sleep.rs

1use std::{mem, pin, task, time};
2
3use crate::{abi, context, core::driver::schedule::clock::timer};
4
5pub const MAXIMUM_DURATION: time::Duration = time::Duration::new(i64::MAX as u64 / 2, 999_999_999);
6
7pub trait TimerExt<'d> {
8    fn sleep(&self, duration: time::Duration) -> Result<Sleep<'d>, Error>;
9}
10
11impl<'d> TimerExt<'d> for timer::Timer<'d> {
12    fn sleep(&self, duration: time::Duration) -> Result<Sleep<'d>, Error> {
13        Sleep::new(*self, duration)
14    }
15}
16
17/// Sleep could not be represented or admitted to the fixed timer store.
18#[derive(Clone, Copy, Debug, Eq, PartialEq)]
19#[repr(u8)]
20pub enum Error {
21    Duration { actual: time::Duration },
22    Capacity,
23}
24
25impl From<timer::Exhausted> for Error {
26    fn from(_: timer::Exhausted) -> Self {
27        Self::Capacity
28    }
29}
30
31#[must_use = "a fiber does nothing unless it is driven"]
32pub struct Sleep<'d> {
33    alarm: timer::Alarm<'d>,
34    state: State,
35}
36
37#[derive(Clone, Copy)]
38enum State {
39    New(time::Duration),
40    Armed,
41    Done,
42}
43
44impl<'d> Sleep<'d> {
45    pub fn new(timer: timer::Timer<'d>, duration: time::Duration) -> Result<Self, Error> {
46        if duration > MAXIMUM_DURATION {
47            return Err(Error::Duration { actual: duration });
48        }
49        Ok(Self {
50            alarm: timer.try_alarm()?,
51            state: State::New(duration),
52        })
53    }
54
55    /// Polls this timer as a leaf of an already admitted application transition.
56    /// Completion is retained here; subsequent polls remain pending.
57    pub fn poll_sleep(
58        &mut self,
59        mut context: pin::Pin<&mut context::Context<'_, 'd>>,
60    ) -> task::Poll<()> {
61        if let State::Done = self.state {
62            return task::Poll::Pending;
63        }
64        let wake = context.as_ref().completion();
65        let now = context.as_mut().driver().driver_ref().clock().now();
66        let polled = if let State::New(duration) = self.state {
67            let polled = self.alarm.arm_and_poll(now.clamp_add(duration), now, wake);
68            self.state = State::Armed;
69            polled
70        } else {
71            self.alarm.poll(now, wake)
72        };
73        if polled.is_ready() {
74            self.state = State::Done;
75        }
76        polled
77    }
78}
79
80impl<'d> abi::Fiber<'d> for Sleep<'d> {
81    type Output = ();
82
83    fn poll(call: context::PollCall<'_, '_, 'd, Self>) -> task::Poll<()> {
84        let (this, context) = call.into_parts();
85        this.get_mut().poll_sleep(context)
86    }
87}
88
89const _: () = assert!(mem::size_of::<Sleep<'static>>() == 4 * mem::size_of::<usize>());
90const _: () = assert!(mem::size_of::<Error>() == 3 * mem::size_of::<usize>());
91const _: () =
92    assert!(mem::size_of::<Result<Sleep<'static>, Error>>() == 4 * mem::size_of::<usize>());