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