timeout_trait/
std_impls.rs

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