hjul/
lib.rs

1#![crate_name = "hjul"]
2#![cfg_attr(feature = "unstable", feature(test))]
3
4#[cfg(feature = "unstable")]
5extern crate test;
6
7mod timers;
8
9pub use timers::{Runner, Timer};
10
11#[cfg(test)]
12mod tests {
13    use super::*;
14    use std::sync::atomic::{AtomicBool, Ordering};
15    use std::sync::Arc;
16    use std::thread;
17    use std::time::{Duration, Instant};
18
19    #[cfg(feature = "unstable")]
20    use test::Bencher;
21
22    /* This test can theoretically fail -- on a VERY slow machine.
23     */
24    #[test]
25    fn test_accuracy() {
26        let capacity = 100;
27        let accuracy = Duration::from_millis(100);
28        let horrison = Duration::from_millis(10_000);
29        let cogs = (horrison.as_nanos() / accuracy.as_nanos()) as usize;
30        let runner = Runner::new(accuracy, cogs, capacity);
31
32        let tests = vec![
33            Duration::from_millis(100),
34            Duration::from_millis(200),
35            Duration::from_millis(250),
36            Duration::from_millis(200),
37            Duration::from_millis(400),
38            Duration::from_millis(600),
39            Duration::from_millis(700),
40            Duration::from_millis(100),
41            Duration::from_millis(500),
42            Duration::from_millis(500),
43        ];
44
45        // create and start the timers
46        let mut checks: Vec<Arc<AtomicBool>> = vec![];
47        let mut timers: Vec<Timer> = vec![];
48        for _ in 0..(capacity / tests.len()) {
49            for &dur in &tests {
50                let fired = Arc::new(AtomicBool::new(false));
51                let fcopy = fired.clone();
52                let start = Instant::now();
53                let timer = runner.timer(move || {
54                    let delta = Instant::now() - start;
55                    assert!(
56                        delta >= dur - accuracy,
57                        "at least (duration - accuracy) time should pass"
58                    );
59                    assert!(
60                        delta + accuracy >= dur,
61                        "no more than (duration + accuracy) time should pass"
62                    );
63                    fcopy.store(true, Ordering::SeqCst);
64                });
65                timer.reset(dur);
66                timers.push(timer);
67                checks.push(fired);
68            }
69        }
70
71        // wait for timers to fire
72        let mut longest = tests[0];
73        for &dur in &tests {
74            if dur > longest {
75                longest = dur;
76            }
77            assert!(dur < horrison);
78        }
79        thread::sleep(2 * longest);
80
81        // check that every timer fired
82        for f in checks {
83            assert!(f.load(Ordering::Acquire));
84        }
85    }
86
87    #[cfg(feature = "unstable")]
88    #[bench]
89    fn bench_reset(b: &mut Bencher) {
90        let runner = Runner::new(Duration::from_millis(100), 100, 10);
91        let timer = runner.timer(Box::new(|| {}));
92        b.iter(|| timer.reset(Duration::from_millis(1000)));
93    }
94
95    #[cfg(feature = "unstable")]
96    #[bench]
97    fn bench_start(b: &mut Bencher) {
98        let runner = Runner::new(Duration::from_millis(100), 100, 10);
99        let timer = runner.timer(Box::new(|| {}));
100        b.iter(|| timer.start(Duration::from_millis(1000)));
101    }
102}