timeout_trait/
timeout.rs

1use crate::*;
2
3pub struct TickTimeout<T: TickInstant> {
4    time: T,
5    timeout: TickDuration<T>,
6}
7
8impl<T> TickTimeout<T>
9where
10    T: TickInstant,
11{
12    pub fn nanos(timeout: u32) -> Self {
13        Self::new(TickDuration::from_nanos(timeout))
14    }
15
16    pub fn micros(timeout: u32) -> Self {
17        Self::new(TickDuration::from_micros(timeout))
18    }
19
20    pub fn millis(timeout: u32) -> Self {
21        Self::new(TickDuration::from_millis(timeout))
22    }
23
24    pub fn from_duration(timeout: &TickDuration<T>) -> Self {
25        Self::new(timeout.clone())
26    }
27
28    pub fn new(timeout: TickDuration<T>) -> Self {
29        Self {
30            time: T::now(),
31            timeout,
32        }
33    }
34
35    /// Can be reused without calling `restart()`.
36    #[inline]
37    pub fn timeout(&mut self) -> bool {
38        if self.time.timeout(&self.timeout) {
39            self.time.move_forward(&self.timeout);
40            return true;
41        }
42        false
43    }
44
45    #[inline(always)]
46    pub fn restart(&mut self) {
47        self.time = T::now();
48    }
49
50    #[inline]
51    pub fn time_left(&mut self) -> TickDuration<T> {
52        self.time.time_left(&self.timeout)
53    }
54}
55
56#[cfg(test)]
57mod tests {
58    use super::*;
59    use crate::mock::MockInstant;
60    use fugit::ExtU32;
61
62    #[test]
63    fn tick_timeout() {
64        let mut now = MockInstant::now();
65        assert_eq!(now.elapsed().ticks(), 0);
66        MockInstant::add_time(10.nanos());
67        assert_eq!(now.elapsed().ticks(), 10);
68        MockInstant::add_time(1.millis());
69        assert_eq!(now.elapsed().ticks(), 1_000_010);
70        MockInstant::add_time(10.micros());
71        let mut now2 = MockInstant::now();
72        assert_eq!(now.elapsed().ticks(), 1_010_010);
73        MockInstant::add_time(10.micros());
74        assert_eq!(now2.elapsed().ticks(), 10_000);
75
76        let mut t = TickTimeout::<MockInstant>::nanos(100);
77        assert!(!t.timeout());
78        MockInstant::add_time(10.nanos());
79        assert!(!t.timeout());
80        MockInstant::add_time(90.nanos());
81        assert!(t.timeout());
82        assert!(!t.timeout());
83        MockInstant::add_time(100.nanos());
84        assert!(t.timeout());
85
86        MockInstant::add_time(90.nanos());
87        assert!(!t.timeout());
88        t.restart();
89        MockInstant::add_time(90.nanos());
90        assert!(!t.timeout());
91        MockInstant::add_time(10.nanos());
92        assert!(t.timeout());
93
94        let mut t = TickTimeout::<MockInstant>::micros(100);
95        assert!(!t.timeout());
96        MockInstant::add_time(10.micros());
97        assert!(!t.timeout());
98        MockInstant::add_time(90.micros());
99        assert!(t.timeout());
100        assert!(!t.timeout());
101        MockInstant::add_time(100.micros());
102        assert!(t.timeout());
103
104        MockInstant::add_time(90.micros());
105        assert!(!t.timeout());
106        t.restart();
107        MockInstant::add_time(90.micros());
108        assert!(!t.timeout());
109        MockInstant::add_time(10.micros());
110        assert!(t.timeout());
111
112        let mut t = TickTimeout::<MockInstant>::millis(100);
113        assert!(!t.timeout());
114        MockInstant::add_time(10.millis());
115        assert!(!t.timeout());
116        MockInstant::add_time(90.millis());
117        assert!(t.timeout());
118        assert!(!t.timeout());
119        MockInstant::add_time(100.millis());
120        assert!(t.timeout());
121
122        MockInstant::add_time(90.millis());
123        assert!(!t.timeout());
124        t.restart();
125        MockInstant::add_time(90.millis());
126        assert!(!t.timeout());
127        MockInstant::add_time(10.millis());
128        assert!(t.timeout());
129
130        let mut count = 0;
131        let dur = TickDuration::<MockInstant>::from_nanos(100);
132        let t = MockInstant::now();
133        assert!(t.timeout_with(&dur, || {
134            MockInstant::add_time(10.nanos());
135            count += 1;
136            true
137        }));
138        assert_eq!(count, 10);
139
140        let t = TickTimeout::<MockInstant>::micros(40_000_000);
141        assert_eq!(t.timeout.ticks(), 40_000_000_000);
142
143        let mut t = TickTimeout::<MockInstant>::millis(40_000);
144        assert_eq!(t.timeout.ticks(), 40_000_000_000);
145
146        assert!(!t.timeout());
147
148        for _ in 0..40 {
149            MockInstant::add_time(999.millis());
150            assert!(!t.timeout());
151        }
152        MockInstant::add_time(100.millis());
153        assert!(t.timeout());
154        assert!(!t.timeout());
155
156        for _ in 0..39 {
157            MockInstant::add_time(999.millis());
158            assert!(!t.timeout());
159        }
160        t.restart();
161        for _ in 0..40 {
162            MockInstant::add_time(999.millis());
163            assert!(!t.timeout());
164        }
165        MockInstant::add_time(100.millis());
166        assert!(t.timeout());
167    }
168}
169
170#[cfg(test)]
171mod tests_fugit {
172    use core::ops::Div;
173    use fugit::{
174        ExtU32, ExtU32Ceil, KilohertzU32, MicrosDurationU32, MillisDurationU32, NanosDurationU64,
175        RateExtU32,
176    };
177
178    #[test]
179    fn duration_tick() {
180        assert_eq!(1 / 1000, 0);
181        assert_eq!(1_u32.div(1000), 0);
182        assert_eq!(1_u32.div_ceil(1000), 1);
183
184        let dur: MicrosDurationU32 = 1.micros();
185        assert_eq!(dur.ticks(), 1);
186
187        let dur: MicrosDurationU32 = 1.millis();
188        assert_eq!(dur.ticks(), 1000);
189        assert_eq!(dur.to_millis(), 1);
190
191        let dur: MillisDurationU32 = 1.millis();
192        assert_eq!(dur.ticks(), 1);
193        assert_eq!(dur.to_micros(), 1000);
194
195        let dur: MillisDurationU32 = 1.micros();
196        assert_eq!(dur.ticks(), 0);
197
198        let dur: MillisDurationU32 = 1.micros_at_least();
199        assert_eq!(dur.ticks(), 1);
200
201        let dur: MicrosDurationU32 = 1.micros();
202        assert_eq!(dur.to_millis(), 0);
203        let dur: MillisDurationU32 = dur.ticks().micros_at_least();
204        assert_eq!(dur.ticks(), 1);
205
206        let a = MicrosDurationU32::micros(100);
207        let b = MicrosDurationU32::micros(99);
208        assert!(b < a);
209
210        let a = NanosDurationU64::micros(100);
211        let b = NanosDurationU64::micros(101);
212        assert!(b > a);
213    }
214
215    #[test]
216    fn rate_tick() {
217        let r: KilohertzU32 = 1.MHz();
218        assert_eq!(r.raw(), 1_000);
219        let f: u32 = r.to_Hz();
220        assert_eq!(f, 1_000_000);
221    }
222}