| //! Utilities for tracking time. |
| //! |
| //! This module provides a number of types for executing code after a set period |
| //! of time. |
| //! |
| //! * `Delay` is a future that does no work and completes at a specific `Instant` |
| //! in time. |
| //! |
| //! * `Interval` is a stream yielding a value at a fixed period. It is |
| //! initialized with a `Duration` and repeatedly yields each time the duration |
| //! elapses. |
| //! |
| //! * `Timeout`: Wraps a future or stream, setting an upper bound to the amount |
| //! of time it is allowed to execute. If the future or stream does not |
| //! complete in time, then it is canceled and an error is returned. |
| //! |
| //! * `DelayQueue`: A queue where items are returned once the requested delay |
| //! has expired. |
| //! |
| //! These types are sufficient for handling a large number of scenarios |
| //! involving time. |
| //! |
| //! These types must be used from within the context of the `Runtime`. |
| //! |
| //! # Examples |
| //! |
| //! Wait 100ms and print "Hello World!" |
| //! |
| //! ``` |
| //! use tokio::time::delay_for; |
| //! |
| //! use std::time::Duration; |
| //! |
| //! |
| //! #[tokio::main] |
| //! async fn main() { |
| //! delay_for(Duration::from_millis(100)).await; |
| //! println!("100 ms have elapsed"); |
| //! } |
| //! ``` |
| //! |
| //! Require that an operation takes no more than 300ms. Note that this uses the |
| //! `timeout` function on the `FutureExt` trait. This trait is included in the |
| //! prelude. |
| //! |
| //! ``` |
| //! use tokio::time::{timeout, Duration}; |
| //! |
| //! async fn long_future() { |
| //! // do work here |
| //! } |
| //! |
| //! # async fn dox() { |
| //! let res = timeout(Duration::from_secs(1), long_future()).await; |
| //! |
| //! if res.is_err() { |
| //! println!("operation timed out"); |
| //! } |
| //! # } |
| //! ``` |
| |
| mod clock; |
| pub(crate) use self::clock::Clock; |
| #[cfg(feature = "test-util")] |
| pub use clock::{advance, pause, resume}; |
| |
| pub mod delay_queue; |
| #[doc(inline)] |
| pub use delay_queue::DelayQueue; |
| |
| mod delay; |
| pub use delay::{delay_for, delay_until, Delay}; |
| |
| pub(crate) mod driver; |
| |
| mod error; |
| pub use error::Error; |
| |
| mod instant; |
| pub use self::instant::Instant; |
| |
| mod interval; |
| pub use interval::{interval, interval_at, Interval}; |
| |
| mod timeout; |
| #[doc(inline)] |
| pub use timeout::{timeout, timeout_at, Elapsed, Timeout}; |
| |
| cfg_stream! { |
| mod throttle; |
| pub use throttle::{throttle, Throttle}; |
| } |
| |
| mod wheel; |
| |
| #[cfg(test)] |
| #[cfg(not(loom))] |
| mod tests; |
| |
| // Re-export for convenience |
| pub use std::time::Duration; |
| |
| // ===== Internal utils ===== |
| |
| enum Round { |
| Up, |
| Down, |
| } |
| |
| /// Convert a `Duration` to milliseconds, rounding up and saturating at |
| /// `u64::MAX`. |
| /// |
| /// The saturating is fine because `u64::MAX` milliseconds are still many |
| /// million years. |
| #[inline] |
| fn ms(duration: Duration, round: Round) -> u64 { |
| const NANOS_PER_MILLI: u32 = 1_000_000; |
| const MILLIS_PER_SEC: u64 = 1_000; |
| |
| // Round up. |
| let millis = match round { |
| Round::Up => (duration.subsec_nanos() + NANOS_PER_MILLI - 1) / NANOS_PER_MILLI, |
| Round::Down => duration.subsec_millis(), |
| }; |
| |
| duration |
| .as_secs() |
| .saturating_mul(MILLIS_PER_SEC) |
| .saturating_add(u64::from(millis)) |
| } |