Skip to main content

nuclei/time/
mod.rs

1//! Time: sleeping, timeouts and intervals, on the timer wheel of the shard
2//! that polls them, and the runtime's clock they read.
3//!
4//! The clock is [`Instant`](crate::time::Instant). It runs with the system's monotonic clock until
5//! [`pause`](crate::time::pause) stops it (or a runtime built with
6//! [`start_paused`](crate::Builder::start_paused) starts stopped); a paused
7//! clock moves only by [`advance`](crate::time::advance), or by itself when every shard of its
8//! runtime is idle with a timer armed: it then jumps to the earliest timer, so
9//! code that sleeps runs at once in tests. Timers fire on the wheel's
10//! millisecond: a timer waits at least its duration, rounded up to the next
11//! millisecond, and a shard busy with a task fires it once that task yields.
12//! [`sleep_precise`](crate::time::sleep_precise) waits to the microsecond
13//! instead, off the millisecond wheel: its deadline ends the shard's wait
14//! through the backend's high-resolution timer, and a paused clock moves to
15//! it exactly; `sleep` and `timeout` on the wheel pay nothing for it.
16//! Arming and cancelling a timer on its shard costs no allocation once the
17//! shard's wheel has grown to the most timers alive at once; a timer polled on
18//! a thread that is not a shard (another runtime's) is fired for it by a
19//! shard of the current runtime, or of the default one.
20
21pub(crate) mod clock;
22pub mod error;
23mod instant;
24mod interval;
25#[cfg(all(test, not(loom)))]
26mod nanos_tests;
27mod precise;
28mod sleep;
29mod timeout;
30pub(crate) mod units;
31pub(crate) mod wheel;
32
33pub use self::instant::Instant;
34pub use self::interval::{Interval, MissedTickBehavior, interval, interval_at};
35pub use self::precise::{SleepPrecise, sleep_precise, sleep_until_precise};
36pub(crate) use self::sleep::TimerOp;
37pub use self::sleep::{Sleep, sleep, sleep_until};
38pub use self::timeout::{Timeout, timeout, timeout_at};
39
40use core::time::Duration;
41
42/// Stops the clock of the runtime this code runs in (or of the default
43/// runtime): [`Instant::now`] stands still, and timers fire only as the clock
44/// is moved, by [`advance`] or by itself whenever every shard of the runtime is
45/// idle with a timer armed (it jumps to the earliest one). A paused clock stays
46/// paused.
47///
48/// ```
49/// use std::time::Duration;
50/// use nuclei::time::{self, Instant};
51///
52/// # nuclei::Builder::new().worker_threads(0).build().unwrap().block_on(async {
53/// time::pause();
54/// let start = Instant::now();
55/// // Nothing else runs: the clock jumps to the sleep's end at once.
56/// time::sleep(Duration::from_secs(3600)).await;
57/// assert_eq!(Instant::now() - start, Duration::from_secs(3600));
58/// # });
59/// ```
60pub fn pause() {
61    crate::rt::paused::pause();
62}
63
64/// Starts a paused clock again from the time it stands at; a running clock
65/// goes on as it is.
66pub fn resume() {
67    crate::rt::paused::resume();
68}
69
70/// Moves the clock of the runtime this code runs in forward by `duration`,
71/// paused or running, then lets the timers that came due fire before it
72/// returns.
73///
74/// ```
75/// use std::time::Duration;
76/// use nuclei::time::{self, Instant};
77///
78/// # nuclei::Builder::new().worker_threads(0).build().unwrap().block_on(async {
79/// time::pause();
80/// let start = Instant::now();
81/// time::advance(Duration::from_millis(250)).await;
82/// assert_eq!(start.elapsed(), Duration::from_millis(250));
83/// # });
84/// ```
85pub async fn advance(duration: Duration) {
86    crate::rt::paused::advance(duration);
87    crate::task::yield_now().await;
88}
89
90#[cfg(test)]
91mod tests;