1 use crate::future::poll_fn;
2 use crate::time::{sleep_until, Duration, Instant, Sleep};
3
4 use std::future::Future;
5 use std::pin::Pin;
6 use std::task::{Context, Poll};
7
8 /// Creates new `Interval` that yields with interval of `duration`. The first
9 /// tick completes immediately.
10 ///
11 /// An interval will tick indefinitely. At any time, the `Interval` value can be
12 /// dropped. This cancels the interval.
13 ///
14 /// This function is equivalent to `interval_at(Instant::now(), period)`.
15 ///
16 /// # Panics
17 ///
18 /// This function panics if `period` is zero.
19 ///
20 /// # Examples
21 ///
22 /// ```
23 /// use tokio::time::{self, Duration};
24 ///
25 /// #[tokio::main]
26 /// async fn main() {
27 /// let mut interval = time::interval(Duration::from_millis(10));
28 ///
29 /// interval.tick().await;
30 /// interval.tick().await;
31 /// interval.tick().await;
32 ///
33 /// // approximately 20ms have elapsed.
34 /// }
35 /// ```
36 ///
37 /// A simple example using `interval` to execute a task every two seconds.
38 ///
39 /// The difference between `interval` and [`sleep`] is that an `interval`
40 /// measures the time since the last tick, which means that `.tick().await`
41 /// may wait for a shorter time than the duration specified for the interval
42 /// if some time has passed between calls to `.tick().await`.
43 ///
44 /// If the tick in the example below was replaced with [`sleep`], the task
45 /// would only be executed once every three seconds, and not every two
46 /// seconds.
47 ///
48 /// ```
49 /// use tokio::time;
50 ///
51 /// async fn task_that_takes_a_second() {
52 /// println!("hello");
53 /// time::sleep(time::Duration::from_secs(1)).await
54 /// }
55 ///
56 /// #[tokio::main]
57 /// async fn main() {
58 /// let mut interval = time::interval(time::Duration::from_secs(2));
59 /// for _i in 0..5 {
60 /// interval.tick().await;
61 /// task_that_takes_a_second().await;
62 /// }
63 /// }
64 /// ```
65 ///
66 /// [`sleep`]: crate::time::sleep()
interval(period: Duration) -> Interval67 pub fn interval(period: Duration) -> Interval {
68 assert!(period > Duration::new(0, 0), "`period` must be non-zero.");
69
70 interval_at(Instant::now(), period)
71 }
72
73 /// Creates new `Interval` that yields with interval of `period` with the
74 /// first tick completing at `start`.
75 ///
76 /// An interval will tick indefinitely. At any time, the `Interval` value can be
77 /// dropped. This cancels the interval.
78 ///
79 /// # Panics
80 ///
81 /// This function panics if `period` is zero.
82 ///
83 /// # Examples
84 ///
85 /// ```
86 /// use tokio::time::{interval_at, Duration, Instant};
87 ///
88 /// #[tokio::main]
89 /// async fn main() {
90 /// let start = Instant::now() + Duration::from_millis(50);
91 /// let mut interval = interval_at(start, Duration::from_millis(10));
92 ///
93 /// interval.tick().await;
94 /// interval.tick().await;
95 /// interval.tick().await;
96 ///
97 /// // approximately 70ms have elapsed.
98 /// }
99 /// ```
interval_at(start: Instant, period: Duration) -> Interval100 pub fn interval_at(start: Instant, period: Duration) -> Interval {
101 assert!(period > Duration::new(0, 0), "`period` must be non-zero.");
102
103 Interval {
104 delay: Box::pin(sleep_until(start)),
105 period,
106 }
107 }
108
109 /// Interval returned by [`interval`](interval) and [`interval_at`](interval_at).
110 ///
111 /// This type allows you to wait on a sequence of instants with a certain
112 /// duration between each instant. Unlike calling [`sleep`](crate::time::sleep)
113 /// in a loop, this lets you count the time spent between the calls to `sleep`
114 /// as well.
115 ///
116 /// An `Interval` can be turned into a `Stream` with [`IntervalStream`].
117 ///
118 /// [`IntervalStream`]: https://docs.rs/tokio-stream/0.1/tokio_stream/wrappers/struct.IntervalStream.html
119 #[derive(Debug)]
120 pub struct Interval {
121 /// Future that completes the next time the `Interval` yields a value.
122 delay: Pin<Box<Sleep>>,
123
124 /// The duration between values yielded by `Interval`.
125 period: Duration,
126 }
127
128 impl Interval {
129 /// Completes when the next instant in the interval has been reached.
130 ///
131 /// # Examples
132 ///
133 /// ```
134 /// use tokio::time;
135 ///
136 /// use std::time::Duration;
137 ///
138 /// #[tokio::main]
139 /// async fn main() {
140 /// let mut interval = time::interval(Duration::from_millis(10));
141 ///
142 /// interval.tick().await;
143 /// interval.tick().await;
144 /// interval.tick().await;
145 ///
146 /// // approximately 20ms have elapsed.
147 /// }
148 /// ```
tick(&mut self) -> Instant149 pub async fn tick(&mut self) -> Instant {
150 poll_fn(|cx| self.poll_tick(cx)).await
151 }
152
153 /// Poll for the next instant in the interval to be reached.
154 ///
155 /// This method can return the following values:
156 ///
157 /// * `Poll::Pending` if the next instant has not yet been reached.
158 /// * `Poll::Ready(instant)` if the next instant has been reached.
159 ///
160 /// When this method returns `Poll::Pending`, the current task is scheduled
161 /// to receive a wakeup when the instant has elapsed. Note that on multiple
162 /// calls to `poll_tick`, only the `Waker` from the `Context` passed to the
163 /// most recent call is scheduled to receive a wakeup.
poll_tick(&mut self, cx: &mut Context<'_>) -> Poll<Instant>164 pub fn poll_tick(&mut self, cx: &mut Context<'_>) -> Poll<Instant> {
165 // Wait for the delay to be done
166 ready!(Pin::new(&mut self.delay).poll(cx));
167
168 // Get the `now` by looking at the `delay` deadline
169 let now = self.delay.deadline();
170
171 // The next interval value is `duration` after the one that just
172 // yielded.
173 let next = now + self.period;
174 self.delay.as_mut().reset(next);
175
176 // Return the current instant
177 Poll::Ready(now)
178 }
179 }
180