dark_std/sync/
duration.rs

1use std::sync::atomic::{AtomicUsize, Ordering};
2use std::time::Duration;
3
4// atomic duration in milli seconds
5#[derive(Debug)]
6pub struct AtomicDuration(AtomicUsize);
7
8impl AtomicDuration {
9    pub fn new(dur: Option<Duration>) -> Self {
10        let dur = match dur {
11            None => 0,
12            Some(d) => dur_to_ms(d) as usize,
13        };
14        AtomicDuration(AtomicUsize::new(dur))
15    }
16
17    #[inline]
18    pub fn get(&self) -> Option<Duration> {
19        match self.0.load(Ordering::Relaxed) {
20            0 => None,
21            d => Some(Duration::from_millis(d as u64)),
22        }
23    }
24
25    #[inline]
26    pub fn store(&self, dur: Option<Duration>) {
27        let timeout = match dur {
28            None => 0,
29            Some(d) => dur_to_ms(d) as usize,
30        };
31
32        self.0.store(timeout, Ordering::Relaxed);
33    }
34
35    #[inline]
36    pub fn take(&self) -> Option<Duration> {
37        match self.0.swap(0, Ordering::Relaxed) {
38            0 => None,
39            d => Some(Duration::from_millis(d as u64)),
40        }
41    }
42
43    #[inline]
44    pub fn into_inner(self) -> Option<Duration> {
45        self.take()
46    }
47}
48
49fn dur_to_ms(dur: Duration) -> u64 {
50    // Note that a duration is a (u64, u32) (seconds, nanoseconds) pair
51    const MS_PER_SEC: u64 = 1_000;
52    const NANOS_PER_MILLI: u64 = 1_000_000;
53    let ns = u64::from(dur.subsec_nanos());
54    let ms = (ns + NANOS_PER_MILLI - 1) / NANOS_PER_MILLI;
55    dur.as_secs().saturating_mul(MS_PER_SEC).saturating_add(ms)
56}