moirai_async/timer/
interval.rs1use std::future::Future;
2use std::pin::Pin;
3use std::task::{Context, Poll};
4use std::time::{Duration, Instant};
5
6use crate::timer::clamped_deadline;
7use crate::timer::delay::Delay;
8
9pub struct Interval {
11 pub(super) next_tick: Instant,
12 pub(super) period: Duration,
13 pub(super) delay: Option<Delay>,
14}
15
16impl Interval {
17 pub(super) fn new(period: Duration) -> Self {
18 let next_tick = clamped_deadline(Instant::now(), period);
19 Self {
20 next_tick,
21 period,
22 delay: None,
23 }
24 }
25
26 pub(super) fn new_at(start: Instant, period: Duration) -> Self {
27 Self {
28 next_tick: start,
29 period,
30 delay: None,
31 }
32 }
33
34 pub fn next_tick(&self) -> Instant {
36 self.next_tick
37 }
38
39 pub fn reset(&mut self) {
41 self.next_tick = clamped_deadline(Instant::now(), self.period);
42 self.delay = None;
43 }
44
45 pub fn set_period(&mut self, period: Duration) {
47 self.period = period;
48 self.next_tick = clamped_deadline(Instant::now(), period);
49 self.delay = None;
50 }
51
52 pub async fn next(&mut self) -> Instant {
54 if self.delay.is_none() {
55 self.delay = Some(Delay::until(self.next_tick));
56 }
57
58 if let Some(delay) = &mut self.delay {
59 delay.await;
60 let tick_time = self.next_tick;
61 self.next_tick = clamped_deadline(self.next_tick, self.period);
62 self.delay = None;
63 tick_time
64 } else {
65 Instant::now()
66 }
67 }
68}
69
70impl Future for Interval {
71 type Output = Instant;
72
73 fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
74 if self.delay.is_none() {
75 self.delay = Some(Delay::until(self.next_tick));
76 }
77
78 if let Some(delay) = &mut self.delay {
79 match Pin::new(delay).poll(cx) {
80 Poll::Ready(()) => {
81 let tick_time = self.next_tick;
82 let period = self.period;
83 self.next_tick = clamped_deadline(self.next_tick, period);
84 self.delay = None;
85 Poll::Ready(tick_time)
86 }
87 Poll::Pending => Poll::Pending,
88 }
89 } else {
90 Poll::Pending
91 }
92 }
93}