moka/common/time/
atomic_time.rs

1use crate::common::time::Instant;
2
3use portable_atomic::AtomicU64;
4use std::sync::atomic::Ordering;
5
6/// `AtomicInstant` is a wrapper around `AtomicU64` that provides thread-safe access
7/// to an `Instant`.
8///
9/// `u64::MAX` is used to represent an unset `Instant`.
10#[derive(Debug)]
11pub(crate) struct AtomicInstant {
12    instant: AtomicU64,
13}
14
15impl Default for AtomicInstant {
16    /// Creates a new `AtomicInstant` with an unset `Instant`.
17    fn default() -> Self {
18        Self {
19            instant: AtomicU64::new(u64::MAX),
20        }
21    }
22}
23
24impl AtomicInstant {
25    /// Creates a new `AtomicInstant` with the given `Instant`.
26    pub(crate) fn new(instant: Instant) -> Self {
27        // Ensure the `Instant` is not `u64::MAX`, which means unset.
28        debug_assert!(instant.as_nanos() != u64::MAX);
29
30        Self {
31            instant: AtomicU64::new(instant.as_nanos()),
32        }
33    }
34
35    /// Clears the `Instant`.
36    pub(crate) fn clear(&self) {
37        self.instant.store(u64::MAX, Ordering::Release);
38    }
39
40    /// Returns `true` if the `Instant` is set.
41    pub(crate) fn is_set(&self) -> bool {
42        self.instant.load(Ordering::Acquire) != u64::MAX
43    }
44
45    /// Returns the `Instant` if it is set, otherwise `None`.
46    pub(crate) fn instant(&self) -> Option<Instant> {
47        let ts = self.instant.load(Ordering::Acquire);
48        if ts == u64::MAX {
49            None
50        } else {
51            Some(Instant::from_nanos(ts))
52        }
53    }
54
55    /// Sets the `Instant`.
56    pub(crate) fn set_instant(&self, instant: Instant) {
57        // Ensure the `Instant` is not `u64::MAX`, which means unset.
58        debug_assert!(instant.as_nanos() != u64::MAX);
59
60        self.instant.store(instant.as_nanos(), Ordering::Release);
61    }
62}