1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
use crate::common::time::{clock::Instant as ClockInstant, Instant};

use std::{
    any::TypeId,
    sync::atomic::{AtomicU64, Ordering},
};

#[derive(Debug)]
pub(crate) struct AtomicInstant {
    instant: AtomicU64,
}

impl Default for AtomicInstant {
    fn default() -> Self {
        Self {
            instant: AtomicU64::new(u64::MAX),
        }
    }
}

// TODO: Need a safe way to convert between `quanta::Instant` and `u64`.
// quanta v0.10.0 no longer provides `quanta::Instant::as_u64` method.

impl AtomicInstant {
    pub(crate) fn new(timestamp: Instant) -> Self {
        let ai = Self::default();
        ai.set_instant(timestamp);
        ai
    }

    pub(crate) fn clear(&self) {
        self.instant.store(u64::MAX, Ordering::Release);
    }

    pub(crate) fn is_set(&self) -> bool {
        self.instant.load(Ordering::Acquire) != u64::MAX
    }

    pub(crate) fn instant(&self) -> Option<Instant> {
        let ts = self.instant.load(Ordering::Acquire);
        if ts == u64::MAX {
            None
        } else {
            debug_assert_eq!(
                TypeId::of::<ClockInstant>(),
                TypeId::of::<quanta::Instant>()
            );
            Some(Instant::new(unsafe {
                std::mem::transmute::<u64, quanta::Instant>(ts)
            }))
        }
    }

    pub(crate) fn set_instant(&self, instant: Instant) {
        debug_assert_eq!(
            TypeId::of::<ClockInstant>(),
            TypeId::of::<quanta::Instant>()
        );
        let ts = unsafe { std::mem::transmute::<quanta::Instant, u64>(instant.inner_clock()) };
        self.instant.store(ts, Ordering::Release);
    }
}