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 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
36/// [`TimeoutState`] implementation for.
37pub 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}