1use std::sync::Mutex;
4use std::sync::PoisonError;
5use std::time::{Duration, Instant};
6
7pub trait Clock: Send + Sync + 'static {
17 fn now(&self) -> Instant;
19}
20
21#[derive(Clone, Copy, Debug, Default)]
28pub struct MonotonicClock;
29
30impl Clock for MonotonicClock {
31 #[inline]
32 fn now(&self) -> Instant {
33 Instant::now()
34 }
35}
36
37#[derive(Debug)]
48pub struct ManualClock {
49 now: Mutex<Instant>,
50}
51
52impl ManualClock {
53 #[must_use]
55 pub fn new() -> ManualClock {
56 ManualClock {
57 now: Mutex::new(Instant::now()),
58 }
59 }
60
61 pub fn advance(&self, by: Duration) {
63 let mut now = self.now.lock().unwrap_or_else(PoisonError::into_inner);
64 *now = now.checked_add(by).unwrap_or(*now);
65 }
66
67 pub fn set(&self, at: Instant) {
77 let mut now = self.now.lock().unwrap_or_else(PoisonError::into_inner);
78 if at > *now {
79 *now = at;
80 }
81 }
82}
83
84impl Default for ManualClock {
85 fn default() -> ManualClock {
86 ManualClock::new()
87 }
88}
89
90impl Clock for ManualClock {
91 fn now(&self) -> Instant {
92 *self.now.lock().unwrap_or_else(PoisonError::into_inner)
93 }
94}
95
96#[cfg(test)]
97mod tests {
98 use super::*;
99
100 #[test]
101 fn test_manual_clock_frozen_until_advanced() {
102 let c = ManualClock::new();
103 let a = c.now();
104 std::thread::sleep(Duration::from_millis(2));
105 assert_eq!(c.now(), a);
106 c.advance(Duration::from_millis(5));
107 assert_eq!(c.now(), a + Duration::from_millis(5));
108 }
109
110 #[test]
111 fn test_manual_clock_set_forward_only() {
112 let c = ManualClock::new();
113 let a = c.now();
114 c.set(a + Duration::from_secs(3));
115 c.set(a);
116 assert_eq!(c.now(), a + Duration::from_secs(3));
117 }
118}