agnostic_lite/time/interval.rs
1use core::{
2 task::{Context, Poll},
3 time::Duration,
4};
5
6use futures_util::stream::Stream;
7
8/// The interval abstraction for a runtime.
9pub trait AsyncInterval: Stream<Item = Self::Instant> + Send + Unpin {
10 /// The instant type
11 type Instant: super::Instant;
12
13 /// Resets the interval to a [`Duration`]. Sets the next tick after the specified [`Duration`].
14 ///
15 /// The behavior of this function may different in different runtime implementations.
16 fn reset(&mut self, interval: Duration);
17
18 /// Resets the interval to a specific instant. Sets the next tick to expire at the given instant.
19 ///
20 /// The behavior of this function may different in different runtime implementations.
21 fn reset_at(&mut self, instant: Self::Instant);
22
23 /// Polls for the next instant in the interval to be reached.
24 ///
25 /// This method can return the following values:
26 ///
27 /// * `Poll::Pending` if the next instant has not yet been reached.
28 /// * `Poll::Ready(instant)` if the next instant has been reached.
29 ///
30 /// When this method returns `Poll::Pending`, the current task is scheduled
31 /// to receive a wakeup when the instant has elapsed. Note that on multiple
32 /// calls to `poll_tick`, only the [`Waker`](std::task::Waker) from the
33 /// [`Context`](std::task::Context) passed to the most recent call is scheduled to receive a
34 /// wakeup.
35 fn poll_tick(&mut self, cx: &mut Context<'_>) -> Poll<Self::Instant>;
36}
37
38impl<T> AsyncInterval for T
39where
40 T: Send + AsyncLocalInterval,
41 T::Instant: Send,
42{
43 type Instant = T::Instant;
44
45 fn reset(&mut self, interval: Duration) {
46 AsyncLocalInterval::reset(self, interval)
47 }
48
49 fn reset_at(&mut self, instant: Self::Instant) {
50 AsyncLocalInterval::reset_at(self, instant)
51 }
52
53 fn poll_tick(&mut self, cx: &mut Context<'_>) -> Poll<Self::Instant> {
54 AsyncLocalInterval::poll_tick(self, cx)
55 }
56}
57
58impl<T> AsyncIntervalExt for T
59where
60 T: Send + AsyncLocalIntervalExt,
61 T::Instant: Send,
62{
63 fn interval(period: Duration) -> Self
64 where
65 Self: Sized,
66 {
67 AsyncLocalIntervalExt::interval_local(period)
68 }
69
70 fn interval_at(start: Self::Instant, period: Duration) -> Self
71 where
72 Self: Sized,
73 {
74 AsyncLocalIntervalExt::interval_local_at(start, period)
75 }
76}
77
78/// Extension trait for [`AsyncInterval`].
79pub trait AsyncIntervalExt: AsyncInterval {
80 /// Creates a timer that emits events periodically.
81 fn interval(period: Duration) -> Self
82 where
83 Self: Sized;
84
85 /// Creates a timer that emits events periodically, starting at `start`.
86 fn interval_at(start: Self::Instant, period: Duration) -> Self
87 where
88 Self: Sized;
89}
90
91/// Like [`AsyncInterval`], but does not require `Send`.
92pub trait AsyncLocalInterval: Stream<Item = Self::Instant> + Unpin {
93 /// The instant type
94 type Instant: super::Instant;
95
96 /// Resets the interval to a [`Duration`]. Sets the next tick after the specified [`Duration`].
97 ///
98 /// The behavior of this function may different in different runtime implementations.
99 fn reset(&mut self, interval: Duration);
100
101 /// Resets the interval to a specific instant. Sets the next tick to expire at the given instant.
102 ///
103 /// The behavior of this function may different in different runtime implementations.
104 fn reset_at(&mut self, instant: Self::Instant);
105
106 /// Polls for the next instant in the interval to be reached.
107 ///
108 /// This method can return the following values:
109 ///
110 /// * `Poll::Pending` if the next instant has not yet been reached.
111 /// * `Poll::Ready(instant)` if the next instant has been reached.
112 ///
113 /// When this method returns `Poll::Pending`, the current task is scheduled
114 /// to receive a wakeup when the instant has elapsed. Note that on multiple
115 /// calls to `poll_tick`, only the [`Waker`](std::task::Waker) from the
116 /// [`Context`](std::task::Context) passed to the most recent call is scheduled to receive a
117 /// wakeup.
118 fn poll_tick(&mut self, cx: &mut Context<'_>) -> Poll<Self::Instant>;
119}
120
121/// Extension trait for [`AsyncLocalInterval`].
122pub trait AsyncLocalIntervalExt: AsyncInterval {
123 /// Creates a timer that emits events periodically.
124 fn interval_local(period: Duration) -> Self
125 where
126 Self: Sized;
127
128 /// Creates a timer that emits events periodically, starting at `start`.
129 fn interval_local_at(start: Self::Instant, period: Duration) -> Self
130 where
131 Self: Sized;
132}