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