dope_fiber/task/time/
sleep.rs1use 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#[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 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>());