waiter_trait/
counter.rs

1use super::*;
2
3/// The timeout condition is independent of time
4/// and is determined solely by the number of times `timeout()` is called.
5///
6/// # Examples
7///
8/// ```
9/// use waiter_trait::{prelude::*, Counter};
10///
11/// let c = Counter::new(0);
12/// let mut t = c.start();
13/// assert!(t.timeout());
14/// assert!(t.timeout());
15///
16/// let c = Counter::new(usize::MAX);
17/// let mut t = c.start();
18/// assert!(!t.timeout());
19/// assert!(!t.timeout());
20///
21/// let c = Counter::new(2);
22/// let mut t = c.start();
23/// assert!(!t.timeout());
24/// assert!(!t.timeout());
25/// assert!(t.timeout());
26/// assert!(t.timeout());
27///
28/// t.restart();
29/// assert!(!t.timeout());
30/// assert!(!t.timeout());
31/// assert!(t.timeout());
32/// assert!(t.timeout());
33/// ```
34pub struct Counter {
35    retry_times: usize,
36}
37
38impl Counter {
39    /// - `retry_times`: The number of calls to `timeout()` before it returns `true`.
40    ///     - If set to `0`, `timeout()` always returns `true`
41    ///     - If set to `usize::MAX`, `timeout()` always returns `false`
42    pub fn new(retry_times: usize) -> Self {
43        Self { retry_times }
44    }
45}
46
47impl Waiter for Counter {
48    #[inline]
49    fn start(&self) -> impl WaiterStatus {
50        CounterInstance {
51            count: 0,
52            waiter: self,
53        }
54    }
55}
56
57pub struct CounterInstance<'a> {
58    count: usize,
59    waiter: &'a Counter,
60}
61
62impl<'a> WaiterStatus for CounterInstance<'a> {
63    #[inline]
64    fn timeout(&mut self) -> bool {
65        if self.waiter.retry_times == usize::MAX {
66            return false;
67        }
68
69        if self.count < self.waiter.retry_times {
70            self.count = self.count.wrapping_add(1);
71            false
72        } else {
73            true
74        }
75    }
76
77    #[inline(always)]
78    fn restart(&mut self) {
79        self.count = 0;
80    }
81}