Skip to main content

qubit_clock/
lib.rs

1// =============================================================================
2//    Copyright (c) 2025 - 2026 Haixing Hu.
3//
4//    SPDX-License-Identifier: Apache-2.0
5//
6//    Licensed under the Apache License, Version 2.0.
7// =============================================================================
8#![cfg_attr(docsrs, feature(doc_cfg))]
9//! Injectable wall clocks, monotonic clocks, and deterministic timers.
10//!
11//! Wall time and monotonic time are deliberately separate. Long-lived
12//! services can inject [`WallClock`] for business timestamps, while timeout
13//! and delay code injects [`MonotonicClock`] or [`Timer`]. A
14//! [`BlockingSleeper`] can adapt the same timer when synchronous code must
15//! block, provided the timer backend can progress while the calling thread is
16//! parked. Manual implementations allow tests to advance logical time without
17//! waiting for real time to pass.
18//!
19//! # Examples
20//!
21//! A manual timer can drive a blocking sleep without waiting for real time:
22//!
23//! ```
24//! use qubit_clock::{
25//!     BlockingSleeper, ManualMonotonicClock, MonotonicClock,
26//! };
27//! use std::time::Duration;
28//!
29//! let clock = ManualMonotonicClock::new_shared();
30//! let sleeper = BlockingSleeper::new(clock.new_timer());
31//! let worker = std::thread::spawn(move || {
32//!     sleeper
33//!         .sleep_for(Duration::from_secs(5))
34//!         .expect("manual sleep should complete");
35//! });
36//!
37//! assert!(clock.wait_for_waiters(1, Duration::from_secs(1)));
38//! clock
39//!     .advance(Duration::from_secs(5))
40//!     .expect("manual time should advance");
41//! worker.join().expect("sleeping thread should finish");
42//! ```
43
44pub(crate) mod internal;
45
46pub mod error;
47pub mod monotonic;
48pub mod sleep;
49#[cfg(feature = "test-util")]
50#[cfg_attr(docsrs, doc(cfg(feature = "test-util")))]
51pub mod test_util;
52pub mod timer;
53pub mod wall;
54
55#[cfg(feature = "tokio")]
56pub use error::TokioRuntimeError;
57pub use error::{
58    TimeError,
59    TimerUnavailableError,
60};
61pub use monotonic::{
62    ClockDomain,
63    ManualDeadlineFuture,
64    ManualMonotonicClock,
65    ManualWaiterFuture,
66    MonotonicClock,
67    MonotonicInstant,
68    StdMonotonicClock,
69};
70pub use sleep::BlockingSleeper;
71pub use timer::{
72    ManualTimer,
73    StdTimer,
74    Timer,
75    TimerFuture,
76};
77pub use wall::{
78    FixedWallClock,
79    ManualWallClock,
80    StdWallClock,
81    WallClock,
82};
83
84// qubit-style: allow coverage-cfg
85#[doc(hidden)]
86#[cfg(coverage)]
87pub use timer::internal::std_timer_scheduler::{
88    fail_next_std_timer_worker_spawn,
89    panic_next_std_timer_worker,
90    reset_std_timer_worker_notification_count,
91    std_timer_worker_notification_count,
92};
93
94#[doc(hidden)]
95#[cfg(all(coverage, feature = "tokio"))]
96pub use timer::panic_next_tokio_timer_sleep_poll;
97
98#[cfg(feature = "tokio")]
99pub use monotonic::TokioMonotonicClock;
100#[cfg(feature = "tokio")]
101pub use timer::TokioTimer;