waiter_trait/
tick_waiter.rs1use super::*;
2use core::marker::PhantomData;
3
4pub struct TickWaiter<T, I, N> {
32 timeout_tick: N,
33 interval: I,
34 _t: PhantomData<T>,
35}
36
37impl<T, I> TickWaiter<T, I, u32>
38where
39 T: TickInstant,
40 I: Interval,
41{
42 pub fn us(timeout_us: u32, interval: I, frequency: u32) -> Self {
43 let timeout_tick = (timeout_us as u64)
44 .checked_mul(frequency as u64)
45 .unwrap()
46 .div_ceil(1_000_000);
47 assert!(timeout_tick <= u32::MAX as u64);
48 Self {
49 timeout_tick: timeout_tick as u32,
50 interval,
51 _t: PhantomData,
52 }
53 }
54}
55
56impl<T, I> TickWaiter<T, I, u64>
57where
58 T: TickInstant,
59 I: Interval,
60{
61 pub fn ns(timeout_ns: u64, interval: I, frequency: u32) -> Self {
63 assert_eq!(frequency % 1_000_000, 0);
64 let timeout_tick = timeout_ns
65 .checked_mul((frequency / 1_000_000) as u64)
66 .unwrap()
67 .div_ceil(1_000);
68 Self {
69 timeout_tick,
70 interval,
71 _t: PhantomData,
72 }
73 }
74}
75
76impl<T, I, N> Waiter for TickWaiter<T, I, N>
77where
78 N: Num,
79 T: TickInstant,
80 I: Interval,
81{
82 fn start(&self) -> impl WaiterTime {
83 TickWaiterTime::<T, I, N> {
84 tick: T::now(),
85 elapsed_tick: N::ZERO,
86 waiter: self,
87 }
88 }
89}
90
91pub struct TickWaiterTime<'a, T: TickInstant, I: Interval, N: Num> {
92 tick: T,
93 elapsed_tick: N,
94 waiter: &'a TickWaiter<T, I, N>,
95}
96
97impl<'a, T, I, N> WaiterTime for TickWaiterTime<'a, T, I, N>
98where
99 N: Num,
100 T: TickInstant,
101 I: Interval,
102{
103 #[inline]
105 fn timeout(&mut self) -> bool {
106 let now = T::now();
107 self.elapsed_tick = self.elapsed_tick.add_u32(now.tick_since(self.tick));
108 self.tick = now;
109
110 if self.elapsed_tick >= self.waiter.timeout_tick {
111 self.elapsed_tick -= self.waiter.timeout_tick;
112 true
113 } else {
114 self.waiter.interval.interval();
115 false
116 }
117 }
118
119 #[inline(always)]
120 fn restart(&mut self) {
121 self.tick = T::now();
122 self.elapsed_tick = N::ZERO;
123 }
124}
125
126pub trait Num: Sized + Copy + core::cmp::Ord + core::ops::SubAssign {
127 const ZERO: Self;
128 fn add_u32(self, v: u32) -> Self;
129}
130
131impl Num for u32 {
132 const ZERO: Self = 0;
133 fn add_u32(self, v: u32) -> Self {
134 self.saturating_add(v)
135 }
136}
137
138impl Num for u64 {
139 const ZERO: Self = 0u64;
140 fn add_u32(self, v: u32) -> Self {
141 self.saturating_add(v as u64)
142 }
143}