devtime/
sync.rs

1use crate::state::{FakeTimeState, Signal, SleepWaiter, Sleeper};
2use std::ops::Add;
3use std::sync::mpsc::Sender;
4use std::sync::{mpsc, Arc, Mutex};
5use std::thread;
6use std::time::{Duration, Instant, SystemTime};
7
8trait Time {
9    fn monotonic_now(&self) -> Instant;
10    fn system_now(&self) -> SystemTime;
11    fn sleep(&self, duration: Duration);
12    fn sleep_until(&self, dst: Instant);
13}
14
15pub struct RealTime {}
16
17impl Time for RealTime {
18    fn monotonic_now(&self) -> Instant {
19        Instant::now()
20    }
21
22    fn system_now(&self) -> SystemTime {
23        SystemTime::now()
24    }
25
26    fn sleep(&self, duration: Duration) {
27        thread::sleep(duration);
28    }
29
30    fn sleep_until(&self, dst: Instant) {
31        thread::sleep(dst.saturating_duration_since(Instant::now()));
32    }
33}
34
35#[derive(Clone)]
36pub struct FakeTime(Arc<Mutex<FakeTimeState<Sender<()>>>>);
37
38impl FakeTime {
39    pub fn advance(&self, d: Duration) {
40        self.0.lock().unwrap().advance(d);
41    }
42    pub fn wait_exact_sleepers_count(&self, count: usize) {
43        let (tx, rx) = mpsc::channel();
44        let waiter = SleepWaiter { count, signal: tx };
45        self.0.lock().unwrap().add_sleep_waiter(waiter);
46        rx.recv().unwrap();
47    }
48}
49
50impl Time for FakeTime {
51    fn monotonic_now(&self) -> Instant {
52        return self.0.lock().unwrap().monotonic();
53    }
54
55    fn system_now(&self) -> SystemTime {
56        return self.0.lock().unwrap().real();
57    }
58
59    fn sleep(&self, duration: Duration) {
60        self.sleep_until(self.monotonic_now().add(duration))
61    }
62
63    fn sleep_until(&self, dst: Instant) {
64        let (tx, rx) = mpsc::channel::<()>();
65        {
66            let sleeper = Sleeper {
67                monotonic: dst,
68                signal: tx,
69            };
70
71            self.0.lock().unwrap().add_sleeper(sleeper);
72        }
73        rx.recv().unwrap();
74    }
75}
76
77impl Default for FakeTime {
78    fn default() -> Self {
79        return FakeTime(Arc::new(Mutex::new(FakeTimeState::default())));
80    }
81}
82
83#[cfg(test)]
84mod test {
85    use super::*;
86    use std::sync::atomic::Ordering::Relaxed;
87    use std::sync::atomic::{AtomicBool, Ordering};
88
89    #[test]
90    fn test_sleep() {
91        let clock = FakeTime::default();
92        let dst = clock.monotonic_now().add(Duration::from_secs(60));
93        let clock2 = clock.clone();
94        let thread_worked = Arc::new(AtomicBool::new(false));
95        let thread_worked2 = thread_worked.clone();
96        let handler = thread::spawn(move || {
97            clock2.sleep_until(dst);
98            assert_eq!(dst, clock2.monotonic_now());
99            thread_worked2.store(true, Relaxed);
100        });
101
102        clock.advance(Duration::from_secs(60));
103        handler.join().unwrap();
104        assert_eq!(true, thread_worked.load(Relaxed));
105    }
106
107    #[test]
108    fn test_wait_sleepers() {
109        let clock = FakeTime::default();
110        let clock2 = clock.clone();
111        let dst = clock.monotonic_now().add(Duration::from_secs(60));
112        let thread_worked = Arc::new(AtomicBool::new(false));
113        let thread_worked2 = thread_worked.clone();
114        let handler = thread::spawn(move || {
115            clock2.sleep(Duration::from_secs(60));
116            assert_eq!(dst, clock2.monotonic_now());
117            thread_worked2.store(true, Relaxed);
118        });
119        clock.wait_exact_sleepers_count(1);
120        clock.advance(Duration::from_secs(60));
121        handler.join().unwrap();
122        assert_eq!(true, thread_worked.load(Relaxed));
123    }
124}
125
126impl Signal for Sender<()> {
127    fn signal(&self) {
128        let _ = self.send(());
129    }
130}