compio_runtime\time/
future.rs1use std::{
2 cell::RefCell,
3 pin::Pin,
4 rc::Rc,
5 task::{Context, Poll},
6 time::{Duration, Instant},
7};
8
9use pin_project_lite::pin_project;
10
11use crate::{
12 Runtime,
13 time::{Elapsed, TimerRuntime, runtime::TimerKey, sleep_until},
14};
15
16#[derive(Debug)]
17pub(crate) struct TimerFuture {
18 key: TimerKey,
19 rt: Rc<RefCell<TimerRuntime>>,
20}
21
22impl TimerFuture {
23 pub fn try_new(instant: Instant) -> Option<Self> {
30 Runtime::with_current(|rt| {
31 let key = rt.timer_runtime.borrow_mut().insert(instant)?;
32 Some(Self {
33 key,
34 rt: rt.timer_runtime.clone(),
35 })
36 })
37 }
38}
39
40impl Future for TimerFuture {
41 type Output = ();
42
43 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
44 self.rt.borrow_mut().poll_timer(cx, &self.key)
45 }
46}
47
48impl Drop for TimerFuture {
49 fn drop(&mut self) {
50 self.rt.borrow_mut().cancel(&self.key)
51 }
52}
53
54compio_driver::assert_not_impl!(TimerFuture, Send);
55compio_driver::assert_not_impl!(TimerFuture, Sync);
56
57#[must_use = "Futures do nothing unless polled."]
60#[derive(Debug)]
61pub struct Sleep(Option<TimerFuture>);
62
63impl Sleep {
64 #[inline]
65 pub(crate) fn new(instant: Instant) -> Self {
66 Sleep(TimerFuture::try_new(instant))
67 }
68}
69
70impl Future for Sleep {
71 type Output = ();
72
73 fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
74 if let Some(timer) = self.0.as_mut() {
75 Pin::new(timer).poll(cx)
76 } else {
77 Poll::Ready(())
78 }
79 }
80}
81
82pin_project! {
83 #[must_use = "Futures do nothing unless polled."]
85 #[derive(Debug)]
86 pub struct Timeout<F> {
87 #[pin]
88 fut: F,
89 sleep: Sleep,
90 }
91}
92
93impl<F: Future> Timeout<F> {
94 pub(crate) fn new(instant: Instant, fut: F) -> Self {
95 Self {
96 fut,
97 sleep: Sleep::new(instant),
98 }
99 }
100}
101
102impl<F: Future> Future for Timeout<F> {
103 type Output = Result<F::Output, Elapsed>;
104
105 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
106 let me = self.project();
107
108 if let Poll::Ready(out) = me.fut.poll(cx) {
109 return Poll::Ready(Ok(out));
110 }
111
112 match Pin::new(me.sleep).poll(cx) {
113 Poll::Ready(()) => Poll::Ready(Err(Elapsed(()))),
114 Poll::Pending => Poll::Pending,
115 }
116 }
117}
118
119#[derive(Debug)]
129pub struct Interval {
130 first_ticked: bool,
131 start: Instant,
132 period: Duration,
133}
134
135impl Interval {
136 pub(crate) fn new(start: Instant, period: Duration) -> Self {
137 Self {
138 first_ticked: false,
139 start,
140 period,
141 }
142 }
143
144 pub async fn tick(&mut self) -> Instant {
149 if !self.first_ticked {
150 sleep_until(self.start).await;
151 self.first_ticked = true;
152 self.start
153 } else {
154 let now = Instant::now();
155 let next = now + self.period
156 - Duration::from_nanos(
157 ((now - self.start).as_nanos() % self.period.as_nanos()) as _,
158 );
159 sleep_until(next).await;
160 next
161 }
162 }
163}