tokio_util/time/
mod.rs

1//! Additional utilities for tracking time.
2//!
3//! This module provides additional utilities for executing code after a set period
4//! of time. Currently there is only one:
5//!
6//! * `DelayQueue`: A queue where items are returned once the requested delay
7//!   has expired.
8//!
9//! This type must be used from within the context of the `Runtime`.
10
11use std::future::Future;
12use std::time::Duration;
13use tokio::time::Timeout;
14
15mod wheel;
16
17pub mod delay_queue;
18
19#[doc(inline)]
20pub use delay_queue::DelayQueue;
21
22/// A trait which contains a variety of convenient adapters and utilities for `Future`s.
23pub trait FutureExt: Future {
24    /// A wrapper around [`tokio::time::timeout`], with the advantage that it is easier to write
25    /// fluent call chains.
26    ///
27    /// # Examples
28    ///
29    /// ```rust
30    /// use tokio::{sync::oneshot, time::Duration};
31    /// use tokio_util::time::FutureExt;
32    ///
33    /// # async fn dox() {
34    /// let (tx, rx) = oneshot::channel::<()>();
35    ///
36    /// let res = rx.timeout(Duration::from_millis(10)).await;
37    /// assert!(res.is_err());
38    /// # }
39    /// ```
40    fn timeout(self, timeout: Duration) -> Timeout<Self>
41    where
42        Self: Sized,
43    {
44        tokio::time::timeout(timeout, self)
45    }
46}
47
48impl<T: Future + ?Sized> FutureExt for T {}
49
50// ===== Internal utils =====
51
52enum Round {
53    Up,
54    Down,
55}
56
57/// Convert a `Duration` to milliseconds, rounding up and saturating at
58/// `u64::MAX`.
59///
60/// The saturating is fine because `u64::MAX` milliseconds are still many
61/// million years.
62#[inline]
63fn ms(duration: Duration, round: Round) -> u64 {
64    const NANOS_PER_MILLI: u32 = 1_000_000;
65    const MILLIS_PER_SEC: u64 = 1_000;
66
67    // Round up.
68    let millis = match round {
69        Round::Up => (duration.subsec_nanos() + NANOS_PER_MILLI - 1) / NANOS_PER_MILLI,
70        Round::Down => duration.subsec_millis(),
71    };
72
73    duration
74        .as_secs()
75        .saturating_mul(MILLIS_PER_SEC)
76        .saturating_add(u64::from(millis))
77}