t2t_clock/lib.rs
1//! Clocks that read the time: the OS's wall and monotonic clocks, the CPU's counter, and
2//! clocks set by hand.
3//!
4//! Each clock gives its reading through one verb, [`Clock::now`], and the reading's type says
5//! which timeline it came from: subtracting an [`Uptime`] from a [`Timestamp`] does not compile.
6//!
7//! | Clock | Reads | Steps? | For |
8//! | ---------------------- | -------------- | ------- | ---------------------------------------- |
9//! | `SystemClock` | `Timestamp` | yes | a stamp other machines compare |
10//! | `CoarseSystemClock` | `Timestamp` | yes | whether a heartbeat or expiry is due |
11//! | `TaiClock` (Linux) | `TaiTimestamp` | yes | a stamp on the timescale PTP keeps |
12//! | `MonotonicClock` | `Uptime` | never | a deadline, a timeout |
13//! | `CoarseMonotonicClock` | `Uptime` | never | a far deadline, polled often |
14//! | `RawMonotonicClock` | `RawUptime` | never | a span no time service's slewing touches |
15//! | `BootClock` | `BootUptime` | never | a timeout that runs through a suspension |
16//! | `ProcessCpuClock` | `Timedelta` | never | the CPU time the process has used |
17//! | `ThreadCpuClock` | `Timedelta` | never | the CPU time the calling thread has used |
18//! | [`Counter`] | [`Tickstamp`] | never | a stamp or a span in one instruction |
19//! | [`ManualClock`] | any point | by hand | a test or a replay on one thread |
20//! | [`AtomicManualClock`] | any point | by hand | a test or a replay shared across threads |
21//!
22//! The OS clocks need the `std` feature, on 64-bit Linux or macOS, and read the clock the
23//! table's name says on each; each clock's docs give the ids. [`Counter`] reads the virtual counter
24//! on `aarch64` and the time-stamp counter on `x86_64`, with or without `std`.
25//!
26//! # Examples
27//! ```
28//! use t2t_clock::{Clock, ManualClock};
29//! use t2t_core::{Timedelta, Timestamp};
30//!
31//! /// Whether the sample stamped at `stamp` is older than a second.
32//! fn is_stale<C: Clock<Reading = Timestamp>>(clock: &C, stamp: Timestamp) -> bool {
33//! clock.now() - stamp > Timedelta::SECOND
34//! }
35//!
36//! let clock = ManualClock::new(Timestamp::from_secs(10));
37//! assert!(!is_stale(&clock, Timestamp::from_secs(10)), "fresh at capture");
38//! clock.advance(Timedelta::from_secs(2));
39//! assert!(is_stale(&clock, Timestamp::from_secs(10)), "stale two seconds on");
40//! ```
41//!
42//! # Crate Features
43//!
44//! None is on by default, and nothing reaches the operating system unless `std` is named; what
45//! `std` adds is on 64-bit Linux and macOS.
46//!
47//! | Feature | Adds |
48//! | ------- | ------------------------------------------------------ |
49//! | `std` | the OS clocks, and an `x86_64` counter's measured rate |
50//!
51//! [`Timestamp`]: t2t_core::Timestamp
52//! [`Uptime`]: t2t_core::Uptime
53//! [`Tickstamp`]: t2t_core::Tickstamp
54
55#![no_std]
56#![cfg_attr(docsrs, feature(doc_cfg))]
57// docs.rs names what the OS clocks and the counter need in words, as their re-exports below say
58// it, and never by the aliases `build.rs` declares; AtomicManualClock, which builds wherever a
59// 64-bit atomic does, shows none.
60#![cfg_attr(docsrs, doc(auto_cfg(hide(os_clocks, tai_clock, counter, atomic_clock))))]
61
62#[cfg(test)]
63extern crate alloc;
64#[cfg(test)]
65extern crate std;
66
67mod clock;
68#[cfg(counter)]
69mod counter;
70#[cfg(counter)]
71mod errors;
72mod manual;
73#[cfg(os_clocks)]
74#[cfg_attr(
75 docsrs,
76 doc(cfg(all(
77 feature = "std",
78 target_pointer_width = "64",
79 any(target_os = "linux", target_os = "macos")
80 )))
81)]
82mod os;
83#[cfg(atomic_clock)]
84mod sync;
85
86pub use crate::clock::Clock;
87#[cfg(counter)]
88#[cfg_attr(docsrs, doc(cfg(any(target_arch = "aarch64", target_arch = "x86_64"))))]
89pub use crate::counter::Counter;
90#[cfg(counter)]
91#[cfg_attr(docsrs, doc(cfg(any(target_arch = "aarch64", target_arch = "x86_64"))))]
92pub use crate::errors::CounterError;
93#[cfg(atomic_clock)]
94pub use crate::manual::AtomicManualClock;
95pub use crate::manual::ManualClock;
96#[cfg(tai_clock)]
97#[cfg_attr(
98 docsrs,
99 doc(cfg(all(feature = "std", target_pointer_width = "64", target_os = "linux")))
100)]
101pub use crate::os::TaiClock;
102#[cfg(os_clocks)]
103#[cfg_attr(
104 docsrs,
105 doc(cfg(all(
106 feature = "std",
107 target_pointer_width = "64",
108 any(target_os = "linux", target_os = "macos")
109 )))
110)]
111pub use crate::os::{
112 BootClock, CoarseMonotonicClock, CoarseSystemClock, MonotonicClock, ProcessCpuClock,
113 RawMonotonicClock, SystemClock, ThreadCpuClock,
114};