benchmark_counters/
interval_checker.rs

1use std::time::{Duration, Instant};
2
3pub struct IntervalChecker {
4    min: Duration,
5    max: Duration,
6    last_interval: Option<Instant>,
7    interval_counter: usize,
8    errors: usize,
9}
10
11impl IntervalChecker {
12    pub fn new(min: Duration, max: Duration) -> IntervalChecker {
13        IntervalChecker {
14            min,
15            max,
16            last_interval: None,
17            interval_counter: 0,
18            errors: 0,
19        }
20    }
21
22    pub fn tick<F>(&mut self, callback: F) -> bool
23    where
24        F: FnOnce(&IntervalChecker, &Duration),
25    {
26        let mut success = true;
27        if let Some(last_interval) = self.last_interval {
28            let elapsed = last_interval.elapsed();
29            if elapsed > self.max || elapsed < self.min {
30                self.errors += 1;
31                success = false;
32                callback(self, &elapsed);
33            }
34        }
35        self.last_interval = Some(Instant::now());
36        self.interval_counter += 1;
37        success
38    }
39}
40
41#[cfg(test)]
42mod tests {
43    use super::*;
44    use std::thread;
45
46    #[test]
47    fn test_interval() {
48        let mut c = IntervalChecker::new(Duration::from_millis(100), Duration::from_millis(1000));
49        c.tick(|_, _| panic!());
50        thread::sleep(Duration::from_millis(200));
51        c.tick(|_, _| panic!());
52        thread::sleep(Duration::from_millis(20));
53        let mut called = false;
54        c.tick(|checker, elapsed| {
55            called = true;
56            assert!(elapsed.as_millis() < 100 && elapsed.as_millis() >= 20);
57            assert_eq!(2, checker.interval_counter);
58            assert_eq!(1, checker.errors);
59        });
60        assert!(called);
61    }
62}