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
11 use std::future::Future;
12 use std::time::Duration;
13 use tokio::time::Timeout;
14
15 mod wheel;
16
17 pub mod delay_queue;
18
19 #[doc(inline)]
20 pub use delay_queue::DelayQueue;
21
22 /// A trait which contains a variety of convenient adapters and utilities for `Future`s.
23 pub 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 /// ```
timeout(self, timeout: Duration) -> Timeout<Self> where Self: Sized,40 fn timeout(self, timeout: Duration) -> Timeout<Self>
41 where
42 Self: Sized,
43 {
44 tokio::time::timeout(timeout, self)
45 }
46 }
47
48 impl<T: Future + ?Sized> FutureExt for T {}
49
50 // ===== Internal utils =====
51
52 enum 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]
ms(duration: Duration, round: Round) -> u6463 fn 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 }
78