1use std::sync::Arc;
6use std::time::Duration;
7use std::time::Instant;
8
9use sync::Mutex;
10
11use super::Event;
12use super::EventWaitResult;
13use super::FakeClock;
14use super::RawDescriptor;
15use super::Result;
16use crate::descriptor::AsRawDescriptor;
17use crate::descriptor::FromRawDescriptor;
18use crate::descriptor::IntoRawDescriptor;
19use crate::descriptor::SafeDescriptor;
20
21pub trait TimerTrait: AsRawDescriptor + IntoRawDescriptor + Send {
24 fn reset_oneshot(&mut self, dur: Duration) -> Result<()>;
26
27 fn reset_repeating(&mut self, dur: Duration) -> Result<()>;
29
30 fn wait(&mut self) -> Result<()>;
32
33 fn mark_waited(&mut self) -> Result<bool>;
40
41 fn clear(&mut self) -> Result<()>;
43
44 fn resolution(&self) -> Result<Duration>;
46}
47
48pub struct Timer {
49 pub(crate) handle: SafeDescriptor,
50 pub(crate) interval: Option<Duration>,
51}
52
53impl Timer {
54 pub fn try_clone(&self) -> std::result::Result<Timer, std::io::Error> {
57 self.handle
58 .try_clone()
59 .map(|handle| Timer {
60 handle,
61 interval: self.interval,
62 })
63 .map_err(|err| std::io::Error::from_raw_os_error(err.errno()))
64 }
65}
66
67#[derive(PartialEq, Eq, Debug)]
72enum WaitResult {
73 Expired,
74 Timeout,
75}
76
77impl AsRawDescriptor for Timer {
78 fn as_raw_descriptor(&self) -> RawDescriptor {
79 self.handle.as_raw_descriptor()
80 }
81}
82
83impl FromRawDescriptor for Timer {
84 unsafe fn from_raw_descriptor(handle: RawDescriptor) -> Self {
85 Timer {
86 handle: SafeDescriptor::from_raw_descriptor(handle),
87 interval: None,
88 }
89 }
90}
91
92impl IntoRawDescriptor for Timer {
93 fn into_raw_descriptor(self) -> RawDescriptor {
94 self.handle.into_raw_descriptor()
95 }
96}
97
98pub struct FakeTimer {
100 clock: Arc<Mutex<FakeClock>>,
101 deadline_ns: Option<u64>,
102 interval: Option<Duration>,
103 event: Event,
104}
105
106impl FakeTimer {
107 pub fn new(clock: Arc<Mutex<FakeClock>>) -> Self {
110 FakeTimer {
111 clock,
112 deadline_ns: None,
113 interval: None,
114 event: Event::new().unwrap(),
115 }
116 }
117
118 fn reset(&mut self, dur: Duration) -> Result<()> {
119 let mut guard = self.clock.lock();
120 let deadline = guard.nanos() + dur.as_nanos() as u64;
121 self.deadline_ns = Some(deadline);
122 guard.add_event(deadline, self.event.try_clone()?);
123 Ok(())
124 }
125
126 fn wait_for(&mut self, timeout: Option<Duration>) -> Result<WaitResult> {
134 let wait_start = Instant::now();
135 loop {
136 if let Some(timeout) = timeout {
137 let elapsed = Instant::now() - wait_start;
138 if let Some(remaining) = elapsed.checked_sub(timeout) {
139 if let EventWaitResult::TimedOut = self.event.wait_timeout(remaining)? {
140 return Ok(WaitResult::Timeout);
141 }
142 } else {
143 return Ok(WaitResult::Timeout);
144 }
145 } else {
146 self.event.wait()?;
147 }
148
149 if let Some(deadline_ns) = &mut self.deadline_ns {
150 let mut guard = self.clock.lock();
151 let now = guard.nanos();
152 if now >= *deadline_ns {
153 let mut expirys = 0;
154 if let Some(interval) = self.interval {
155 let interval_ns = interval.as_nanos() as u64;
156 if interval_ns > 0 {
157 expirys += (now - *deadline_ns) / interval_ns;
158 *deadline_ns += (expirys + 1) * interval_ns;
159 guard.add_event(*deadline_ns, self.event.try_clone()?);
160 }
161 }
162 return Ok(WaitResult::Expired);
163 }
164 }
165 }
166 }
167}
168
169impl TimerTrait for FakeTimer {
170 fn reset_oneshot(&mut self, dur: Duration) -> Result<()> {
171 self.interval = None;
172 self.reset(dur)
173 }
174
175 fn reset_repeating(&mut self, dur: Duration) -> Result<()> {
176 self.interval = Some(dur);
177 self.reset(dur)
178 }
179
180 fn wait(&mut self) -> Result<()> {
181 self.wait_for(None).map(|_| ())
182 }
183
184 fn mark_waited(&mut self) -> Result<bool> {
185 if let WaitResult::Timeout = self.wait_for(Some(Duration::from_secs(0)))? {
188 Ok(true)
189 } else {
190 Ok(false)
191 }
192 }
193
194 fn clear(&mut self) -> Result<()> {
195 self.deadline_ns = None;
196 self.interval = None;
197 Ok(())
198 }
199
200 fn resolution(&self) -> Result<Duration> {
201 Ok(Duration::from_nanos(1))
202 }
203}
204
205impl AsRawDescriptor for FakeTimer {
206 fn as_raw_descriptor(&self) -> RawDescriptor {
207 self.event.as_raw_descriptor()
208 }
209}
210impl IntoRawDescriptor for FakeTimer {
211 fn into_raw_descriptor(self) -> RawDescriptor {
212 self.event.into_raw_descriptor()
213 }
214}
215
216#[cfg(test)]
217mod tests {
218 use std::time::Duration;
219 #[cfg(not(windows))]
220 use std::time::Instant;
221
222 use super::*;
223 use crate::EventToken;
224 use crate::WaitContext;
225
226 #[test]
227 #[cfg(not(windows))] fn one_shot() {
229 let mut tfd = Timer::new().expect("failed to create Timer");
230
231 let dur = Duration::from_millis(10);
232 let now = Instant::now();
233 tfd.reset_oneshot(dur).expect("failed to arm timer");
234 tfd.wait().expect("unable to wait for timer");
235 let elapsed = now.elapsed();
236 assert!(elapsed >= dur, "expected {elapsed:?} >= {dur:?}");
237 }
238
239 #[test]
241 #[cfg(not(windows))] fn one_shot_cloned() {
243 let mut tfd = Timer::new().expect("failed to create Timer");
244 let mut cloned_tfd = tfd.try_clone().expect("failed to clone timer");
245
246 let dur = Duration::from_millis(10);
247 let now = Instant::now();
248 tfd.reset_oneshot(dur).expect("failed to arm timer");
249 cloned_tfd.wait().expect("unable to wait for timer");
250 let elapsed = now.elapsed();
251 assert!(elapsed >= dur, "expected {elapsed:?} >= {dur:?}");
252 }
253
254 #[test]
255 #[cfg(not(windows))] fn repeating() {
257 let mut tfd = Timer::new().expect("failed to create Timer");
258
259 let interval = Duration::from_millis(10);
260 let now = Instant::now();
261 tfd.reset_repeating(interval).expect("failed to arm timer");
262
263 tfd.wait().expect("unable to wait for timer");
264 assert!(now.elapsed() >= interval);
266 tfd.wait().expect("unable to wait for timer");
267 assert!(now.elapsed() >= interval * 2);
269 tfd.wait().expect("unable to wait for timer");
270 assert!(now.elapsed() >= interval * 3);
271 }
272
273 #[test]
274 fn mark_waited_inactive() {
275 let mut tfd = Timer::new().expect("failed to create Timer");
276 tfd.mark_waited().expect("mark_waited failed");
278 }
279
280 #[test]
281 fn mark_waited_active() {
282 let mut tfd = Timer::new().expect("failed to create Timer");
283 tfd.reset_oneshot(Duration::from_nanos(1))
284 .expect("failed to arm timer");
285
286 #[derive(EventToken)]
288 enum Token {
289 Timer,
290 }
291 let wait_ctx: WaitContext<Token> =
292 WaitContext::build_with(&[(&tfd, Token::Timer)]).unwrap();
293 let _events = wait_ctx.wait().unwrap();
294
295 assert!(
296 !tfd.mark_waited().expect("mark_waited failed"),
297 "expected mark_waited to return false",
298 );
299 }
300
301 #[test]
302 fn fake_one_shot() {
303 let clock = Arc::new(Mutex::new(FakeClock::new()));
304 let mut tfd = FakeTimer::new(clock.clone());
305
306 let dur = Duration::from_nanos(200);
307 tfd.reset_oneshot(dur).expect("failed to arm timer");
308
309 clock.lock().add_ns(200);
310
311 assert_eq!(tfd.wait().is_ok(), true);
312 }
313
314 #[test]
315 fn fake_one_shot_timeout() {
316 let clock = Arc::new(Mutex::new(FakeClock::new()));
317 let mut tfd = FakeTimer::new(clock.clone());
318
319 let dur = Duration::from_nanos(200);
320 tfd.reset_oneshot(dur).expect("failed to arm timer");
321
322 clock.lock().add_ns(100);
323 let result = tfd
324 .wait_for(Some(Duration::from_millis(0)))
325 .expect("unable to wait for timer");
326 assert_eq!(result, WaitResult::Timeout);
327 let result = tfd
328 .wait_for(Some(Duration::from_millis(1)))
329 .expect("unable to wait for timer");
330 assert_eq!(result, WaitResult::Timeout);
331
332 clock.lock().add_ns(100);
333 let result = tfd
334 .wait_for(Some(Duration::from_millis(0)))
335 .expect("unable to wait for timer");
336 assert_eq!(result, WaitResult::Expired);
337 }
338
339 #[test]
340 fn fake_repeating() {
341 let clock = Arc::new(Mutex::new(FakeClock::new()));
342 let mut tfd = FakeTimer::new(clock.clone());
343
344 let interval = Duration::from_nanos(100);
345 tfd.reset_repeating(interval).expect("failed to arm timer");
346
347 clock.lock().add_ns(150);
348
349 assert_eq!(tfd.wait().is_ok(), true);
351
352 clock.lock().add_ns(100);
353 assert_eq!(tfd.wait().is_ok(), true);
354 }
355}