1use std::fmt;
35use std::sync::Arc;
36use std::sync::atomic::{AtomicU64, Ordering};
37use std::time::{Duration, Instant, SystemTime};
38
39pub trait Clock: Send + Sync + fmt::Debug {
41 fn now(&self) -> Instant;
43
44 fn system_time(&self) -> SystemTime;
46
47 fn since(&self, earlier: Instant) -> Duration {
49 self.now().saturating_duration_since(earlier)
50 }
51}
52
53pub type SharedClock = Arc<dyn Clock>;
55
56#[derive(Debug, Default, Clone, Copy)]
58pub struct SystemClock;
59
60impl Clock for SystemClock {
61 fn now(&self) -> Instant {
62 Instant::now()
63 }
64
65 fn system_time(&self) -> SystemTime {
66 SystemTime::now()
67 }
68}
69
70pub fn system_clock() -> SharedClock {
72 Arc::new(SystemClock)
73}
74
75#[derive(Debug)]
81pub struct ManualClock {
82 origin: Instant,
83 system_origin: SystemTime,
84 elapsed_nanos: AtomicU64,
85}
86
87impl Default for ManualClock {
88 fn default() -> Self {
89 Self::new()
90 }
91}
92
93impl ManualClock {
94 pub fn new() -> Self {
96 Self::starting_at(SystemTime::now())
97 }
98
99 pub fn starting_at(system_origin: SystemTime) -> Self {
102 Self {
103 origin: Instant::now(),
104 system_origin,
105 elapsed_nanos: AtomicU64::new(0),
106 }
107 }
108
109 pub fn advance(&self, by: Duration) {
111 self.elapsed_nanos
112 .fetch_add(saturating_nanos(by), Ordering::AcqRel);
113 }
114
115 pub fn set_elapsed(&self, elapsed: Duration) {
118 self.elapsed_nanos
119 .fetch_max(saturating_nanos(elapsed), Ordering::AcqRel);
120 }
121
122 pub fn elapsed(&self) -> Duration {
124 Duration::from_nanos(self.elapsed_nanos.load(Ordering::Acquire))
125 }
126}
127
128impl Clock for ManualClock {
129 fn now(&self) -> Instant {
130 self.origin + self.elapsed()
131 }
132
133 fn system_time(&self) -> SystemTime {
134 self.system_origin + self.elapsed()
135 }
136}
137
138fn saturating_nanos(d: Duration) -> u64 {
139 u64::try_from(d.as_nanos()).unwrap_or(u64::MAX)
140}
141
142#[cfg(test)]
143mod tests {
144 use super::*;
145
146 #[test]
147 fn manual_clock_moves_only_when_told() {
148 let clock = ManualClock::starting_at(SystemTime::UNIX_EPOCH);
149 let t0 = clock.now();
150 assert_eq!(clock.now(), t0);
151
152 clock.advance(Duration::from_millis(250));
153 assert_eq!(clock.since(t0), Duration::from_millis(250));
154 assert_eq!(
155 clock.system_time(),
156 SystemTime::UNIX_EPOCH + Duration::from_millis(250)
157 );
158 }
159
160 #[test]
161 fn manual_clock_never_goes_backwards() {
162 let clock = ManualClock::new();
163 clock.set_elapsed(Duration::from_secs(10));
164 clock.set_elapsed(Duration::from_secs(3));
165 assert_eq!(clock.elapsed(), Duration::from_secs(10));
166 }
167
168 #[test]
169 fn since_saturates_for_a_future_instant() {
170 let clock = ManualClock::new();
171 let later = clock.now() + Duration::from_secs(1);
172 assert_eq!(clock.since(later), Duration::ZERO);
173 }
174}