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 from_nanos(timeout: u32) -> Self {
13 Self::new(TickDuration::from_nanos(timeout))
14 }
15
16 pub fn from_micros(timeout: u32) -> Self {
17 Self::new(TickDuration::from_micros(timeout))
18 }
19
20 pub fn from_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 fn new(timeout: TickDuration<T>) -> Self {
29 Self {
30 time: T::now(),
31 timeout,
32 }
33 }
34
35 #[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>::from_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>::from_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>::from_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>::from_micros(40_000_000);
141 assert_eq!(t.timeout.ticks(), 40_000_000_000);
142
143 let mut t = TickTimeout::<MockInstant>::from_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}