exocore_core/time/
atomic_instant.rs

1use std::{sync::atomic::AtomicU64, time::Duration};
2
3use wasm_timer::Instant;
4
5pub struct AtomicInstant {
6    reference: Instant,
7    delta: AtomicU64,
8}
9
10impl AtomicInstant {
11    pub fn new() -> Self {
12        Self {
13            reference: Instant::now(),
14            delta: AtomicU64::new(0),
15        }
16    }
17
18    pub fn get(&self) -> Instant {
19        self.reference + Duration::from_nanos(self.delta.load(std::sync::atomic::Ordering::Relaxed))
20    }
21
22    pub fn elapsed(&self) -> Duration {
23        Instant::now() - self.get()
24    }
25
26    pub fn update(&self, now: Instant) {
27        let delta = now - self.reference;
28        self.delta.store(
29            delta.as_nanos() as u64,
30            std::sync::atomic::Ordering::Relaxed,
31        );
32    }
33
34    pub fn update_now(&self) {
35        self.update(Instant::now())
36    }
37}
38
39impl Default for AtomicInstant {
40    fn default() -> Self {
41        Self::new()
42    }
43}
44
45impl From<Instant> for AtomicInstant {
46    fn from(instant: Instant) -> Self {
47        AtomicInstant {
48            reference: instant,
49            delta: AtomicU64::new(0),
50        }
51    }
52}
53
54#[cfg(test)]
55mod tests {
56    use std::thread::sleep;
57
58    use super::*;
59
60    #[test]
61    fn test_atomic_instant() {
62        let ai = AtomicInstant::new();
63
64        sleep(Duration::from_millis(100));
65        let elapsed = ai.elapsed();
66        assert!(
67            elapsed >= Duration::from_millis(100),
68            "elapsed: {elapsed:?}"
69        );
70
71        ai.update_now();
72        let elapsed = ai.elapsed();
73        assert!(elapsed < Duration::from_millis(100), "elapsed: {elapsed:?}");
74    }
75}