Skip to main content

spawned_rt/
time.rs

1//! Clock and entropy seam for library code.
2//!
3//! In normal builds [`Instant`] is `std::time::Instant` and [`entropy`] reads
4//! the wall clock, so behaviour is identical to calling them directly. Under
5//! `--cfg spawned_sim` both come from the running simulation: `Instant` reads
6//! virtual time and `entropy` is a stream derived from the simulation seed, so
7//! restart windows, shutdown deadlines, backoff jitter and metrics timings are
8//! deterministic per seed and advance in virtual time.
9
10#[cfg(not(all(spawned_sim, feature = "async")))]
11pub use std::time::Instant;
12
13#[cfg(all(spawned_sim, feature = "async"))]
14pub use crate::tasks::sim::Instant;
15
16/// Seed material for jitter and similar randomization: wall-clock nanoseconds
17/// mixed with a process-wide counter (distinct per call), or, under
18/// simulation, the next value of the simulation's entropy stream.
19pub fn entropy() -> u64 {
20    #[cfg(all(spawned_sim, feature = "async"))]
21    {
22        crate::tasks::sim::entropy()
23    }
24    #[cfg(not(all(spawned_sim, feature = "async")))]
25    {
26        static NEXT: std::sync::atomic::AtomicU64 = std::sync::atomic::AtomicU64::new(1);
27        std::time::SystemTime::now()
28            .duration_since(std::time::UNIX_EPOCH)
29            .unwrap_or_default()
30            .as_nanos() as u64
31            ^ NEXT.fetch_add(1, std::sync::atomic::Ordering::Relaxed)
32    }
33}