• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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