1 use crate::time::driver::{Handle, TimerEntry};
2 use crate::time::{error::Error, Duration, Instant};
3
4 use pin_project_lite::pin_project;
5 use std::future::Future;
6 use std::pin::Pin;
7 use std::task::{self, Poll};
8
9 /// Waits until `deadline` is reached.
10 ///
11 /// No work is performed while awaiting on the sleep future to complete. `Sleep`
12 /// operates at millisecond granularity and should not be used for tasks that
13 /// require high-resolution timers.
14 ///
15 /// # Cancellation
16 ///
17 /// Canceling a sleep instance is done by dropping the returned future. No additional
18 /// cleanup work is required.
19 // Alias for old name in 0.x
20 #[cfg_attr(docsrs, doc(alias = "delay_until"))]
sleep_until(deadline: Instant) -> Sleep21 pub fn sleep_until(deadline: Instant) -> Sleep {
22 Sleep::new_timeout(deadline)
23 }
24
25 /// Waits until `duration` has elapsed.
26 ///
27 /// Equivalent to `sleep_until(Instant::now() + duration)`. An asynchronous
28 /// analog to `std::thread::sleep`.
29 ///
30 /// No work is performed while awaiting on the sleep future to complete. `Sleep`
31 /// operates at millisecond granularity and should not be used for tasks that
32 /// require high-resolution timers.
33 ///
34 /// To run something regularly on a schedule, see [`interval`].
35 ///
36 /// The maximum duration for a sleep is 68719476734 milliseconds (approximately 2.2 years).
37 ///
38 /// # Cancellation
39 ///
40 /// Canceling a sleep instance is done by dropping the returned future. No additional
41 /// cleanup work is required.
42 ///
43 /// # Examples
44 ///
45 /// Wait 100ms and print "100 ms have elapsed".
46 ///
47 /// ```
48 /// use tokio::time::{sleep, Duration};
49 ///
50 /// #[tokio::main]
51 /// async fn main() {
52 /// sleep(Duration::from_millis(100)).await;
53 /// println!("100 ms have elapsed");
54 /// }
55 /// ```
56 ///
57 /// [`interval`]: crate::time::interval()
58 // Alias for old name in 0.x
59 #[cfg_attr(docsrs, doc(alias = "delay_for"))]
sleep(duration: Duration) -> Sleep60 pub fn sleep(duration: Duration) -> Sleep {
61 match Instant::now().checked_add(duration) {
62 Some(deadline) => sleep_until(deadline),
63 None => sleep_until(Instant::far_future()),
64 }
65 }
66
67 pin_project! {
68 /// Future returned by [`sleep`](sleep) and [`sleep_until`](sleep_until).
69 ///
70 /// This type does not implement the `Unpin` trait, which means that if you
71 /// use it with [`select!`] or by calling `poll`, you have to pin it first.
72 /// If you use it with `.await`, this does not apply.
73 ///
74 /// # Examples
75 ///
76 /// Wait 100ms and print "100 ms have elapsed".
77 ///
78 /// ```
79 /// use tokio::time::{sleep, Duration};
80 ///
81 /// #[tokio::main]
82 /// async fn main() {
83 /// sleep(Duration::from_millis(100)).await;
84 /// println!("100 ms have elapsed");
85 /// }
86 /// ```
87 ///
88 /// Use with [`select!`]. Pinning the `Sleep` with [`tokio::pin!`] is
89 /// necessary when the same `Sleep` is selected on multiple times.
90 /// ```no_run
91 /// use tokio::time::{self, Duration, Instant};
92 ///
93 /// #[tokio::main]
94 /// async fn main() {
95 /// let sleep = time::sleep(Duration::from_millis(10));
96 /// tokio::pin!(sleep);
97 ///
98 /// loop {
99 /// tokio::select! {
100 /// () = &mut sleep => {
101 /// println!("timer elapsed");
102 /// sleep.as_mut().reset(Instant::now() + Duration::from_millis(50));
103 /// },
104 /// }
105 /// }
106 /// }
107 /// ```
108 /// Use in a struct with boxing. By pinning the `Sleep` with a `Box`, the
109 /// `HasSleep` struct implements `Unpin`, even though `Sleep` does not.
110 /// ```
111 /// use std::future::Future;
112 /// use std::pin::Pin;
113 /// use std::task::{Context, Poll};
114 /// use tokio::time::Sleep;
115 ///
116 /// struct HasSleep {
117 /// sleep: Pin<Box<Sleep>>,
118 /// }
119 ///
120 /// impl Future for HasSleep {
121 /// type Output = ();
122 ///
123 /// fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> {
124 /// self.sleep.as_mut().poll(cx)
125 /// }
126 /// }
127 /// ```
128 /// Use in a struct with pin projection. This method avoids the `Box`, but
129 /// the `HasSleep` struct will not be `Unpin` as a consequence.
130 /// ```
131 /// use std::future::Future;
132 /// use std::pin::Pin;
133 /// use std::task::{Context, Poll};
134 /// use tokio::time::Sleep;
135 /// use pin_project_lite::pin_project;
136 ///
137 /// pin_project! {
138 /// struct HasSleep {
139 /// #[pin]
140 /// sleep: Sleep,
141 /// }
142 /// }
143 ///
144 /// impl Future for HasSleep {
145 /// type Output = ();
146 ///
147 /// fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> {
148 /// self.project().sleep.poll(cx)
149 /// }
150 /// }
151 /// ```
152 ///
153 /// [`select!`]: ../macro.select.html
154 /// [`tokio::pin!`]: ../macro.pin.html
155 // Alias for old name in 0.2
156 #[cfg_attr(docsrs, doc(alias = "Delay"))]
157 #[derive(Debug)]
158 #[must_use = "futures do nothing unless you `.await` or poll them"]
159 pub struct Sleep {
160 deadline: Instant,
161
162 // The link between the `Sleep` instance and the timer that drives it.
163 #[pin]
164 entry: TimerEntry,
165 }
166 }
167
168 impl Sleep {
new_timeout(deadline: Instant) -> Sleep169 pub(crate) fn new_timeout(deadline: Instant) -> Sleep {
170 let handle = Handle::current();
171 let entry = TimerEntry::new(&handle, deadline);
172
173 Sleep { deadline, entry }
174 }
175
far_future() -> Sleep176 pub(crate) fn far_future() -> Sleep {
177 Self::new_timeout(Instant::far_future())
178 }
179
180 /// Returns the instant at which the future will complete.
deadline(&self) -> Instant181 pub fn deadline(&self) -> Instant {
182 self.deadline
183 }
184
185 /// Returns `true` if `Sleep` has elapsed.
186 ///
187 /// A `Sleep` instance is elapsed when the requested duration has elapsed.
is_elapsed(&self) -> bool188 pub fn is_elapsed(&self) -> bool {
189 self.entry.is_elapsed()
190 }
191
192 /// Resets the `Sleep` instance to a new deadline.
193 ///
194 /// Calling this function allows changing the instant at which the `Sleep`
195 /// future completes without having to create new associated state.
196 ///
197 /// This function can be called both before and after the future has
198 /// completed.
199 ///
200 /// To call this method, you will usually combine the call with
201 /// [`Pin::as_mut`], which lets you call the method without consuming the
202 /// `Sleep` itself.
203 ///
204 /// # Example
205 ///
206 /// ```
207 /// use tokio::time::{Duration, Instant};
208 ///
209 /// # #[tokio::main(flavor = "current_thread")]
210 /// # async fn main() {
211 /// let sleep = tokio::time::sleep(Duration::from_millis(10));
212 /// tokio::pin!(sleep);
213 ///
214 /// sleep.as_mut().reset(Instant::now() + Duration::from_millis(20));
215 /// # }
216 /// ```
217 ///
218 /// [`Pin::as_mut`]: fn@std::pin::Pin::as_mut
reset(self: Pin<&mut Self>, deadline: Instant)219 pub fn reset(self: Pin<&mut Self>, deadline: Instant) {
220 let me = self.project();
221 me.entry.reset(deadline);
222 *me.deadline = deadline;
223 }
224
poll_elapsed(self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Result<(), Error>>225 fn poll_elapsed(self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Result<(), Error>> {
226 let me = self.project();
227
228 // Keep track of task budget
229 let coop = ready!(crate::coop::poll_proceed(cx));
230
231 me.entry.poll_elapsed(cx).map(move |r| {
232 coop.made_progress();
233 r
234 })
235 }
236 }
237
238 impl Future for Sleep {
239 type Output = ();
240
poll(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Self::Output>241 fn poll(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Self::Output> {
242 // `poll_elapsed` can return an error in two cases:
243 //
244 // - AtCapacity: this is a pathological case where far too many
245 // sleep instances have been scheduled.
246 // - Shutdown: No timer has been setup, which is a mis-use error.
247 //
248 // Both cases are extremely rare, and pretty accurately fit into
249 // "logic errors", so we just panic in this case. A user couldn't
250 // really do much better if we passed the error onwards.
251 match ready!(self.as_mut().poll_elapsed(cx)) {
252 Ok(()) => Poll::Ready(()),
253 Err(e) => panic!("timer error: {}", e),
254 }
255 }
256 }
257