timeout_trait/
std_impls.rs1use super::{
2 fugit::{KilohertzU32, RateExtU32},
3 prelude::*,
4};
5use std::time::{Duration, Instant};
6
7#[derive(Default)]
9pub struct StdTimeoutNs {}
10
11impl TimeoutNs for StdTimeoutNs {
12 type TimeoutState = StdTimeoutState;
13
14 fn start_ns(timeout: u32) -> Self::TimeoutState {
15 StdTimeoutState {
16 timeout: Duration::from_nanos(timeout.into()),
17 start_time: Instant::now(),
18 }
19 }
20
21 fn start_us(timeout: u32) -> Self::TimeoutState {
22 StdTimeoutState {
23 timeout: Duration::from_micros(timeout.into()),
24 start_time: Instant::now(),
25 }
26 }
27
28 fn start_ms(timeout: u32) -> Self::TimeoutState {
29 StdTimeoutState {
30 timeout: Duration::from_millis(timeout.into()),
31 start_time: Instant::now(),
32 }
33 }
34}
35
36pub struct StdTimeoutState {
38 timeout: Duration,
39 start_time: Instant,
40}
41
42impl TimeoutState for StdTimeoutState {
43 #[inline]
44 fn timeout(&mut self) -> bool {
45 if self.start_time.elapsed() >= self.timeout {
46 self.start_time += self.timeout;
47 true
48 } else {
49 false
50 }
51 }
52
53 #[inline(always)]
54 fn restart(&mut self) {
55 self.start_time = Instant::now();
56 }
57}
58
59impl TickInstant for Instant {
60 fn frequency() -> KilohertzU32 {
61 1.MHz()
62 }
63
64 #[inline(always)]
65 fn now() -> Self {
66 Instant::now()
67 }
68
69 #[inline(always)]
70 fn tick_since(self, earlier: Self) -> u32 {
71 self.duration_since(earlier).as_micros() as u32
72 }
73}
74
75#[cfg(test)]
76mod tests {
77 use super::*;
78 use crate::TickTimeoutNs;
79 use std::{thread::sleep, time::Duration};
80
81 struct UseTimeout<T: TimeoutState> {
82 interval: T,
83 }
84
85 fn test_timeout<T: TimeoutNs>() {
86 let mut t = T::start_ms(500);
87 assert!(!t.timeout());
88 sleep(Duration::from_millis(260));
89 assert!(!t.timeout());
90 sleep(Duration::from_millis(260));
91 assert!(t.timeout());
92 assert!(!t.timeout());
93
94 t.restart();
95 assert!(!t.timeout());
96 sleep(Duration::from_millis(260));
97 assert!(!t.timeout());
98 sleep(Duration::from_millis(260));
99 assert!(t.timeout());
100 assert!(!t.timeout());
101
102 assert!(T::ns_with(100, || {
103 sleep(Duration::from_nanos(1));
104 true
105 }));
106
107 let mut u = UseTimeout {
108 interval: T::start_ms(1),
109 };
110 u.interval.timeout();
111 }
112
113 #[test]
114 fn std_timeout() {
115 test_timeout::<StdTimeoutNs>();
116 }
117
118 #[test]
119 fn tick_timeout() {
120 test_timeout::<TickTimeoutNs<Instant>>();
121 }
122
123 #[test]
124 fn tick_instant() {
125 let now = <Instant as TickInstant>::now();
126 sleep(Duration::from_millis(200));
127 assert!(now.tick_elapsed() - 200_000 < 1000);
128 }
129}