Coverage Report

Created: 2025-10-31 06:57

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-1.48.0/src/time/sleep.rs
Line
Count
Source
1
use crate::runtime::time::TimerEntry;
2
use crate::time::{error::Error, Duration, Instant};
3
use crate::util::trace;
4
5
use pin_project_lite::pin_project;
6
use std::future::Future;
7
use std::panic::Location;
8
use std::pin::Pin;
9
use std::task::{self, ready, Poll};
10
11
/// Waits until `deadline` is reached.
12
///
13
/// No work is performed while awaiting on the sleep future to complete. `Sleep`
14
/// operates at millisecond granularity and should not be used for tasks that
15
/// require high-resolution timers.
16
///
17
/// To run something regularly on a schedule, see [`interval`].
18
///
19
/// # Cancellation
20
///
21
/// Canceling a sleep instance is done by dropping the returned future. No additional
22
/// cleanup work is required.
23
///
24
/// # Examples
25
///
26
/// Wait 100ms and print "100 ms have elapsed".
27
///
28
/// ```
29
/// use tokio::time::{sleep_until, Instant, Duration};
30
///
31
/// # #[tokio::main(flavor = "current_thread")]
32
/// # async fn main() {
33
/// sleep_until(Instant::now() + Duration::from_millis(100)).await;
34
/// println!("100 ms have elapsed");
35
/// # }
36
/// ```
37
///
38
/// See the documentation for the [`Sleep`] type for more examples.
39
///
40
/// # Panics
41
///
42
/// This function panics if there is no current timer set.
43
///
44
/// It can be triggered when [`Builder::enable_time`] or
45
/// [`Builder::enable_all`] are not included in the builder.
46
///
47
/// It can also panic whenever a timer is created outside of a
48
/// Tokio runtime. That is why `rt.block_on(sleep(...))` will panic,
49
/// since the function is executed outside of the runtime.
50
/// Whereas `rt.block_on(async {sleep(...).await})` doesn't panic.
51
/// And this is because wrapping the function on an async makes it lazy,
52
/// and so gets executed inside the runtime successfully without
53
/// panicking.
54
///
55
/// [`Sleep`]: struct@crate::time::Sleep
56
/// [`interval`]: crate::time::interval()
57
/// [`Builder::enable_time`]: crate::runtime::Builder::enable_time
58
/// [`Builder::enable_all`]: crate::runtime::Builder::enable_all
59
// Alias for old name in 0.x
60
#[cfg_attr(docsrs, doc(alias = "delay_until"))]
61
#[track_caller]
62
0
pub fn sleep_until(deadline: Instant) -> Sleep {
63
0
    Sleep::new_timeout(deadline, trace::caller_location())
64
0
}
65
66
/// Waits until `duration` has elapsed.
67
///
68
/// Equivalent to `sleep_until(Instant::now() + duration)`. An asynchronous
69
/// analog to `std::thread::sleep`.
70
///
71
/// No work is performed while awaiting on the sleep future to complete. `Sleep`
72
/// operates at millisecond granularity and should not be used for tasks that
73
/// require high-resolution timers. The implementation is platform specific,
74
/// and some platforms (specifically Windows) will provide timers with a
75
/// larger resolution than 1 ms.
76
///
77
/// To run something regularly on a schedule, see [`interval`].
78
///
79
/// # Cancellation
80
///
81
/// Canceling a sleep instance is done by dropping the returned future. No additional
82
/// cleanup work is required.
83
///
84
/// # Examples
85
///
86
/// Wait 100ms and print "100 ms have elapsed".
87
///
88
/// ```
89
/// use tokio::time::{sleep, Duration};
90
///
91
/// # #[tokio::main(flavor = "current_thread")]
92
/// # async fn main() {
93
/// sleep(Duration::from_millis(100)).await;
94
/// println!("100 ms have elapsed");
95
/// # }
96
/// ```
97
///
98
/// See the documentation for the [`Sleep`] type for more examples.
99
///
100
/// # Panics
101
///
102
/// This function panics if there is no current timer set.
103
///
104
/// It can be triggered when [`Builder::enable_time`] or
105
/// [`Builder::enable_all`] are not included in the builder.
106
///
107
/// It can also panic whenever a timer is created outside of a
108
/// Tokio runtime. That is why `rt.block_on(sleep(...))` will panic,
109
/// since the function is executed outside of the runtime.
110
/// Whereas `rt.block_on(async {sleep(...).await})` doesn't panic.
111
/// And this is because wrapping the function on an async makes it lazy,
112
/// and so gets executed inside the runtime successfully without
113
/// panicking.
114
///
115
/// [`Sleep`]: struct@crate::time::Sleep
116
/// [`interval`]: crate::time::interval()
117
/// [`Builder::enable_time`]: crate::runtime::Builder::enable_time
118
/// [`Builder::enable_all`]: crate::runtime::Builder::enable_all
119
// Alias for old name in 0.x
120
#[cfg_attr(docsrs, doc(alias = "delay_for"))]
121
#[cfg_attr(docsrs, doc(alias = "wait"))]
122
#[track_caller]
123
0
pub fn sleep(duration: Duration) -> Sleep {
124
0
    let location = trace::caller_location();
125
126
0
    match Instant::now().checked_add(duration) {
127
0
        Some(deadline) => Sleep::new_timeout(deadline, location),
128
0
        None => Sleep::new_timeout(Instant::far_future(), location),
129
    }
130
0
}
131
132
pin_project! {
133
    /// Future returned by [`sleep`](sleep) and [`sleep_until`](sleep_until).
134
    ///
135
    /// This type does not implement the `Unpin` trait, which means that if you
136
    /// use it with [`select!`] or by calling `poll`, you have to pin it first.
137
    /// If you use it with `.await`, this does not apply.
138
    ///
139
    /// # Examples
140
    ///
141
    /// Wait 100ms and print "100 ms have elapsed".
142
    ///
143
    /// ```
144
    /// use tokio::time::{sleep, Duration};
145
    ///
146
    /// # #[tokio::main(flavor = "current_thread")]
147
    /// # async fn main() {
148
    /// sleep(Duration::from_millis(100)).await;
149
    /// println!("100 ms have elapsed");
150
    /// # }
151
    /// ```
152
    ///
153
    /// Use with [`select!`]. Pinning the `Sleep` with [`tokio::pin!`] is
154
    /// necessary when the same `Sleep` is selected on multiple times.
155
    /// ```no_run
156
    /// use tokio::time::{self, Duration, Instant};
157
    ///
158
    /// # #[tokio::main(flavor = "current_thread")]
159
    /// # async fn main() {
160
    /// let sleep = time::sleep(Duration::from_millis(10));
161
    /// tokio::pin!(sleep);
162
    ///
163
    /// loop {
164
    ///     tokio::select! {
165
    ///         () = &mut sleep => {
166
    ///             println!("timer elapsed");
167
    ///             sleep.as_mut().reset(Instant::now() + Duration::from_millis(50));
168
    ///         },
169
    ///     }
170
    /// }
171
    /// # }
172
    /// ```
173
    /// Use in a struct with boxing. By pinning the `Sleep` with a `Box`, the
174
    /// `HasSleep` struct implements `Unpin`, even though `Sleep` does not.
175
    /// ```
176
    /// use std::future::Future;
177
    /// use std::pin::Pin;
178
    /// use std::task::{Context, Poll};
179
    /// use tokio::time::Sleep;
180
    ///
181
    /// struct HasSleep {
182
    ///     sleep: Pin<Box<Sleep>>,
183
    /// }
184
    ///
185
    /// impl Future for HasSleep {
186
    ///     type Output = ();
187
    ///
188
    ///     fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> {
189
    ///         self.sleep.as_mut().poll(cx)
190
    ///     }
191
    /// }
192
    /// ```
193
    /// Use in a struct with pin projection. This method avoids the `Box`, but
194
    /// the `HasSleep` struct will not be `Unpin` as a consequence.
195
    /// ```
196
    /// use std::future::Future;
197
    /// use std::pin::Pin;
198
    /// use std::task::{Context, Poll};
199
    /// use tokio::time::Sleep;
200
    /// use pin_project_lite::pin_project;
201
    ///
202
    /// pin_project! {
203
    ///     struct HasSleep {
204
    ///         #[pin]
205
    ///         sleep: Sleep,
206
    ///     }
207
    /// }
208
    ///
209
    /// impl Future for HasSleep {
210
    ///     type Output = ();
211
    ///
212
    ///     fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> {
213
    ///         self.project().sleep.poll(cx)
214
    ///     }
215
    /// }
216
    /// ```
217
    ///
218
    /// [`select!`]: ../macro.select.html
219
    /// [`tokio::pin!`]: ../macro.pin.html
220
    #[project(!Unpin)]
221
    // Alias for old name in 0.2
222
    #[cfg_attr(docsrs, doc(alias = "Delay"))]
223
    #[derive(Debug)]
224
    #[must_use = "futures do nothing unless you `.await` or poll them"]
225
    pub struct Sleep {
226
        inner: Inner,
227
228
        // The link between the `Sleep` instance and the timer that drives it.
229
        #[pin]
230
        entry: TimerEntry,
231
    }
232
}
233
234
cfg_trace! {
235
    #[derive(Debug)]
236
    struct Inner {
237
        ctx: trace::AsyncOpTracingCtx,
238
    }
239
}
240
241
cfg_not_trace! {
242
    #[derive(Debug)]
243
    struct Inner {
244
    }
245
}
246
247
impl Sleep {
248
    #[cfg_attr(not(all(tokio_unstable, feature = "tracing")), allow(unused_variables))]
249
    #[track_caller]
250
0
    pub(crate) fn new_timeout(
251
0
        deadline: Instant,
252
0
        location: Option<&'static Location<'static>>,
253
0
    ) -> Sleep {
254
        use crate::runtime::scheduler;
255
0
        let handle = scheduler::Handle::current();
256
0
        let entry = TimerEntry::new(handle, deadline);
257
        #[cfg(all(tokio_unstable, feature = "tracing"))]
258
        let inner = {
259
            let handle = scheduler::Handle::current();
260
            let clock = handle.driver().clock();
261
            let handle = &handle.driver().time();
262
            let time_source = handle.time_source();
263
            let deadline_tick = time_source.deadline_to_tick(deadline);
264
            let duration = deadline_tick.saturating_sub(time_source.now(clock));
265
266
            let location = location.expect("should have location if tracing");
267
            let resource_span = tracing::trace_span!(
268
                parent: None,
269
                "runtime.resource",
270
                concrete_type = "Sleep",
271
                kind = "timer",
272
                loc.file = location.file(),
273
                loc.line = location.line(),
274
                loc.col = location.column(),
275
            );
276
277
            let async_op_span = resource_span.in_scope(|| {
278
                tracing::trace!(
279
                    target: "runtime::resource::state_update",
280
                    duration = duration,
281
                    duration.unit = "ms",
282
                    duration.op = "override",
283
                );
284
285
                tracing::trace_span!("runtime.resource.async_op", source = "Sleep::new_timeout")
286
            });
287
288
            let async_op_poll_span =
289
                async_op_span.in_scope(|| tracing::trace_span!("runtime.resource.async_op.poll"));
290
291
            let ctx = trace::AsyncOpTracingCtx {
292
                async_op_span,
293
                async_op_poll_span,
294
                resource_span,
295
            };
296
297
            Inner { ctx }
298
        };
299
300
        #[cfg(not(all(tokio_unstable, feature = "tracing")))]
301
0
        let inner = Inner {};
302
303
0
        Sleep { inner, entry }
304
0
    }
305
306
0
    pub(crate) fn far_future(location: Option<&'static Location<'static>>) -> Sleep {
307
0
        Self::new_timeout(Instant::far_future(), location)
308
0
    }
309
310
    /// Returns the instant at which the future will complete.
311
0
    pub fn deadline(&self) -> Instant {
312
0
        self.entry.deadline()
313
0
    }
314
315
    /// Returns `true` if `Sleep` has elapsed.
316
    ///
317
    /// A `Sleep` instance is elapsed when the requested duration has elapsed.
318
0
    pub fn is_elapsed(&self) -> bool {
319
0
        self.entry.is_elapsed()
320
0
    }
321
322
    /// Resets the `Sleep` instance to a new deadline.
323
    ///
324
    /// Calling this function allows changing the instant at which the `Sleep`
325
    /// future completes without having to create new associated state.
326
    ///
327
    /// This function can be called both before and after the future has
328
    /// completed.
329
    ///
330
    /// To call this method, you will usually combine the call with
331
    /// [`Pin::as_mut`], which lets you call the method without consuming the
332
    /// `Sleep` itself.
333
    ///
334
    /// # Example
335
    ///
336
    /// ```
337
    /// use tokio::time::{Duration, Instant};
338
    ///
339
    /// # #[tokio::main(flavor = "current_thread")]
340
    /// # async fn main() {
341
    /// let sleep = tokio::time::sleep(Duration::from_millis(10));
342
    /// tokio::pin!(sleep);
343
    ///
344
    /// sleep.as_mut().reset(Instant::now() + Duration::from_millis(20));
345
    /// # }
346
    /// ```
347
    ///
348
    /// See also the top-level examples.
349
    ///
350
    /// [`Pin::as_mut`]: fn@std::pin::Pin::as_mut
351
0
    pub fn reset(self: Pin<&mut Self>, deadline: Instant) {
352
0
        self.reset_inner(deadline);
353
0
    }
354
355
    /// Resets the `Sleep` instance to a new deadline without reregistering it
356
    /// to be woken up.
357
    ///
358
    /// Calling this function allows changing the instant at which the `Sleep`
359
    /// future completes without having to create new associated state and
360
    /// without having it registered. This is required in e.g. the
361
    /// [`crate::time::Interval`] where we want to reset the internal [Sleep]
362
    /// without having it wake up the last task that polled it.
363
0
    pub(crate) fn reset_without_reregister(self: Pin<&mut Self>, deadline: Instant) {
364
0
        let mut me = self.project();
365
0
        me.entry.as_mut().reset(deadline, false);
366
0
    }
367
368
0
    fn reset_inner(self: Pin<&mut Self>, deadline: Instant) {
369
0
        let mut me = self.project();
370
0
        me.entry.as_mut().reset(deadline, true);
371
372
        #[cfg(all(tokio_unstable, feature = "tracing"))]
373
        {
374
            let _resource_enter = me.inner.ctx.resource_span.enter();
375
            me.inner.ctx.async_op_span =
376
                tracing::trace_span!("runtime.resource.async_op", source = "Sleep::reset");
377
            let _async_op_enter = me.inner.ctx.async_op_span.enter();
378
379
            me.inner.ctx.async_op_poll_span =
380
                tracing::trace_span!("runtime.resource.async_op.poll");
381
382
            let duration = {
383
                let clock = me.entry.clock();
384
                let time_source = me.entry.driver().time_source();
385
                let now = time_source.now(clock);
386
                let deadline_tick = time_source.deadline_to_tick(deadline);
387
                deadline_tick.saturating_sub(now)
388
            };
389
390
            tracing::trace!(
391
                target: "runtime::resource::state_update",
392
                duration = duration,
393
                duration.unit = "ms",
394
                duration.op = "override",
395
            );
396
        }
397
0
    }
398
399
0
    fn poll_elapsed(self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Result<(), Error>> {
400
0
        let me = self.project();
401
402
0
        ready!(crate::trace::trace_leaf(cx));
403
404
        // Keep track of task budget
405
        #[cfg(all(tokio_unstable, feature = "tracing"))]
406
        let coop = ready!(trace_poll_op!(
407
            "poll_elapsed",
408
            crate::task::coop::poll_proceed(cx),
409
        ));
410
411
        #[cfg(any(not(tokio_unstable), not(feature = "tracing")))]
412
0
        let coop = ready!(crate::task::coop::poll_proceed(cx));
413
414
0
        let result = me.entry.poll_elapsed(cx).map(move |r| {
415
0
            coop.made_progress();
416
0
            r
417
0
        });
418
419
        #[cfg(all(tokio_unstable, feature = "tracing"))]
420
        return trace_poll_op!("poll_elapsed", result);
421
422
        #[cfg(any(not(tokio_unstable), not(feature = "tracing")))]
423
0
        return result;
424
0
    }
425
}
426
427
impl Future for Sleep {
428
    type Output = ();
429
430
    // `poll_elapsed` can return an error in two cases:
431
    //
432
    // - AtCapacity: this is a pathological case where far too many
433
    //   sleep instances have been scheduled.
434
    // - Shutdown: No timer has been setup, which is a mis-use error.
435
    //
436
    // Both cases are extremely rare, and pretty accurately fit into
437
    // "logic errors", so we just panic in this case. A user couldn't
438
    // really do much better if we passed the error onwards.
439
0
    fn poll(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Self::Output> {
440
        #[cfg(all(tokio_unstable, feature = "tracing"))]
441
        let _res_span = self.inner.ctx.resource_span.clone().entered();
442
        #[cfg(all(tokio_unstable, feature = "tracing"))]
443
        let _ao_span = self.inner.ctx.async_op_span.clone().entered();
444
        #[cfg(all(tokio_unstable, feature = "tracing"))]
445
        let _ao_poll_span = self.inner.ctx.async_op_poll_span.clone().entered();
446
0
        match ready!(self.as_mut().poll_elapsed(cx)) {
447
0
            Ok(()) => Poll::Ready(()),
448
0
            Err(e) => panic!("timer error: {e}"),
449
        }
450
0
    }
451
}