1use std::prelude::v1::*;
2
3use crate::clock::{Clock, ReasonablyRealtime, Reference};
4use crate::nanos::Nanos;
5use std::ops::Add;
6use std::sync::Arc;
7use std::time::Duration;
8
9#[derive(Debug, Clone)]
16pub struct QuantaClock {
17 clock: quanta::Clock,
18}
19
20impl Default for QuantaClock {
21 fn default() -> Self {
22 let clock = quanta::Clock::default();
23 Self { clock }
24 }
25}
26
27impl Clock for QuantaClock {
28 type Instant = QuantaInstant;
29
30 fn now(&self) -> Self::Instant {
31 let nowish = self.clock.raw();
32 QuantaInstant(Nanos::new(self.clock.delta_as_nanos(0, nowish)))
33 }
34}
35
36#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug)]
39pub struct QuantaInstant(Nanos);
40
41impl Add<Nanos> for QuantaInstant {
42 type Output = QuantaInstant;
43
44 fn add(self, other: Nanos) -> QuantaInstant {
45 QuantaInstant(self.0 + other)
46 }
47}
48
49impl Reference for QuantaInstant {
50 fn duration_since(&self, earlier: Self) -> Nanos {
51 self.0.duration_since(earlier.0)
52 }
53
54 fn saturating_sub(&self, duration: Nanos) -> Self {
55 QuantaInstant(self.0.saturating_sub(duration))
56 }
57}
58
59#[derive(Debug, Clone)]
72pub struct QuantaUpkeepClock {
73 clock: quanta::Clock,
74 _handle: Arc<quanta::Handle>,
75 reference: quanta::Instant,
76}
77
78impl QuantaUpkeepClock {
79 pub fn from_interval(interval: Duration) -> Result<QuantaUpkeepClock, quanta::Error> {
81 let builder = quanta::Upkeep::new(interval);
82 Self::from_builder(builder)
83 }
84
85 pub fn from_builder(builder: quanta::Upkeep) -> Result<QuantaUpkeepClock, quanta::Error> {
87 let handle = Arc::new(builder.start()?);
88 let clock = quanta::Clock::default();
89 let reference = clock.recent();
90 Ok(QuantaUpkeepClock {
91 clock,
92 _handle: handle,
93 reference,
94 })
95 }
96}
97
98impl Clock for QuantaUpkeepClock {
99 type Instant = QuantaInstant;
100
101 fn now(&self) -> Self::Instant {
102 QuantaInstant(Nanos::from(
103 self.clock
104 .recent()
105 .saturating_duration_since(self.reference),
106 ))
107 }
108}
109
110impl ReasonablyRealtime for QuantaClock {}
111
112#[cfg(test)]
116mod test {
117 use super::*;
118 use crate::clock::{Clock, QuantaClock, QuantaUpkeepClock, Reference};
119 use crate::nanos::Nanos;
120 use std::thread;
121 use std::time::Duration;
122
123 #[test]
124 fn quanta_impls_coverage() {
125 let one_ns = Nanos::new(1);
126 let c = QuantaClock::default();
127 let now = c.now();
128 assert_ne!(now + one_ns, now);
129 assert_eq!(one_ns, Reference::duration_since(&(now + one_ns), now));
130 assert_eq!(Nanos::new(0), Reference::duration_since(&now, now + one_ns));
131 assert_eq!(
132 Reference::saturating_sub(&(now + Duration::from_nanos(1).into()), one_ns),
133 now
134 );
135 }
136
137 #[test]
138 fn quanta_upkeep_impls_coverage_and_advances() {
139 let one_ns = Nanos::new(1);
140 let c = QuantaUpkeepClock::from_interval(Duration::from_millis(50)).unwrap();
143 let now = c.now();
144 assert_ne!(now + one_ns, now);
145 assert_eq!(one_ns, Reference::duration_since(&(now + one_ns), now));
146 assert_eq!(Nanos::new(0), Reference::duration_since(&now, now + one_ns));
147 assert_eq!(
148 Reference::saturating_sub(&(now + Duration::from_nanos(1).into()), one_ns),
149 now
150 );
151
152 let start = c.now();
155 for i in 0..5 {
156 thread::sleep(Duration::from_millis(250));
157 let now = c.now();
158 assert!(
159 now > start,
160 "now={:?} not after start={:?} on iteration={}",
161 now,
162 start,
163 i
164 );
165 }
166 }
167}