timeout_trait/
std_impls.rs

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