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}