atomic-interval 0.1.4

A tiny implementation of an atomic timer.
Documentation
use atomic_interval::AtomicInterval;
use std::sync::atomic::Ordering;
use std::sync::mpsc;
use std::sync::Arc;
use std::sync::Barrier;
use std::time::Duration;
use std::time::Instant;

fn main() {
    let num_threads = num_cpus::get();
    let num_samples = 1000;
    let period = Duration::from_millis(1);
    let atomic_interval = Arc::new(AtomicInterval::new(period));
    let barrier_start = Arc::new(Barrier::new(num_threads));

    let mut index_iteration = 0;
    loop {
        println!("Iteration: {}", index_iteration);
        index_iteration += 1;

        let (samples_sender, samples_receiver) = mpsc::channel();

        #[allow(clippy::needless_collect)]
        let threads = (0..num_threads)
            .map(|_| {
                let atomic_interval = atomic_interval.clone();
                let samples_sender = samples_sender.clone();
                let barrier_start = barrier_start.clone();

                std::thread::spawn(move || {
                    barrier_start.wait();

                    loop {
                        let sample = loop {
                            if atomic_interval.is_ticked(Ordering::Relaxed, Ordering::Relaxed) {
                                break Instant::now();
                            }
                        };

                        if samples_sender.send(sample).is_err() {
                            break;
                        }
                    }
                })
            })
            .collect::<Vec<_>>();

        let mut samples = Vec::with_capacity(num_samples);
        while samples.len() < num_samples {
            samples.push(samples_receiver.recv().unwrap());
        }

        drop(samples_receiver);
        threads
            .into_iter()
            .for_each(|join_handle| join_handle.join().unwrap());

        samples.sort_unstable();

        let diffs = samples
            .into_iter()
            .as_slice()
            .windows(2)
            .map(|adj| {
                let first = adj[0];
                let second = adj[1];

                second.duration_since(first)
            })
            .collect::<Vec<_>>();

        let min = diffs.iter().min().unwrap();
        let max = diffs.iter().max().unwrap();

        if *min < period {
            let anticip_error = 1_f64 - min.as_secs_f64() / period.as_secs_f64();
            println!(
                "  Max anticipation error: {:.3}% with {:?}",
                anticip_error * 100_f64,
                min
            );
        }

        if period < *max {
            let delay_error = max.as_secs_f64() / period.as_secs_f64() - 1_f64;
            println!(
                "  Max delay error: {:.3}% with {:?}",
                delay_error * 100_f64,
                max
            );
        }
    }
}