moka/common/time/
clock.rs1use std::time::{Duration, Instant as StdInstant};
2
3#[cfg(test)]
4use std::sync::Arc;
5
6#[cfg(test)]
7use parking_lot::RwLock;
8
9use super::Instant;
11
12#[derive(Default, Clone)]
13pub(crate) struct Clock {
14 ty: ClockType,
15}
16
17#[derive(Clone)]
18enum ClockType {
19 Standard { origin: StdInstant },
21 #[cfg(feature = "quanta")]
22 Hybrid {
25 std_origin: StdInstant,
26 quanta_origin: quanta::Instant,
27 },
28 #[cfg(test)]
29 Mocked { mock: Arc<Mock> },
31}
32
33impl Default for ClockType {
34 fn default() -> Self {
39 #[cfg(feature = "quanta")]
40 {
41 return ClockType::Hybrid {
42 std_origin: StdInstant::now(),
43 quanta_origin: quanta::Instant::now(),
44 };
45 }
46
47 #[allow(unreachable_code)]
48 ClockType::Standard {
49 origin: StdInstant::now(),
50 }
51 }
52}
53
54impl Clock {
55 #[cfg(test)]
56 pub(crate) fn mock() -> (Clock, Arc<Mock>) {
58 let mock = Arc::new(Mock::default());
59 let clock = Clock {
60 ty: ClockType::Mocked {
61 mock: Arc::clone(&mock),
62 },
63 };
64 (clock, mock)
65 }
66
67 pub(crate) fn now(&self) -> Instant {
73 match &self.ty {
74 ClockType::Standard { origin } => {
75 Instant::from_duration_since_clock_start(origin.elapsed())
76 }
77 #[cfg(feature = "quanta")]
78 ClockType::Hybrid { std_origin, .. } => {
79 Instant::from_duration_since_clock_start(std_origin.elapsed())
80 }
81 #[cfg(test)]
82 ClockType::Mocked { mock } => Instant::from_duration_since_clock_start(mock.elapsed()),
83 }
84 }
85
86 pub(crate) fn fast_now(&self) -> Instant {
100 match &self.ty {
101 #[cfg(feature = "quanta")]
102 ClockType::Hybrid { quanta_origin, .. } => {
103 Instant::from_duration_since_clock_start(quanta_origin.elapsed())
104 }
105 ClockType::Standard { .. } => self.now(),
106 #[cfg(test)]
107 ClockType::Mocked { .. } => self.now(),
108 }
109 }
110
111 pub(crate) fn to_std_instant(&self, instant: Instant) -> StdInstant {
116 match &self.ty {
117 ClockType::Standard { origin } => {
118 let duration = Duration::from_nanos(instant.as_nanos());
119 *origin + duration
120 }
121 #[cfg(feature = "quanta")]
122 ClockType::Hybrid { std_origin, .. } => {
123 let duration = Duration::from_nanos(instant.as_nanos());
124 *std_origin + duration
125 }
126 #[cfg(test)]
127 ClockType::Mocked { mock } => {
128 let duration = Duration::from_nanos(instant.as_nanos());
129 dbg!(mock.origin + duration)
135 }
136 }
137 }
138}
139
140#[cfg(test)]
141pub(crate) struct Mock {
142 origin: StdInstant,
143 now: RwLock<StdInstant>,
144}
145
146#[cfg(test)]
147impl Default for Mock {
148 fn default() -> Self {
149 let origin = StdInstant::now();
150 Self {
151 origin,
152 now: RwLock::new(origin),
153 }
154 }
155}
156
157#[cfg(test)]
158impl Mock {
159 pub(crate) fn increment(&self, amount: Duration) {
160 *self.now.write() += amount;
161 }
162
163 pub(crate) fn elapsed(&self) -> Duration {
164 self.now.read().duration_since(self.origin)
165 }
166}