devtime 0.2.0

Wrappers for real and fake time for use same code for fast time tests and for real time in production
Documentation
use crate::state::{FakeTimeState, Signal, SleepWaiter, Sleeper};
use std::ops::Add;
use std::sync::mpsc::Sender;
use std::sync::{mpsc, Arc, Mutex};
use std::thread;
use std::time::{Duration, Instant, SystemTime};

trait Time {
    fn monotonic_now(&self) -> Instant;
    fn system_now(&self) -> SystemTime;
    fn sleep(&self, duration: Duration);
    fn sleep_until(&self, dst: Instant);
}

pub struct RealTime {}

impl Time for RealTime {
    fn monotonic_now(&self) -> Instant {
        Instant::now()
    }

    fn system_now(&self) -> SystemTime {
        SystemTime::now()
    }

    fn sleep(&self, duration: Duration) {
        thread::sleep(duration);
    }

    fn sleep_until(&self, dst: Instant) {
        thread::sleep(dst.saturating_duration_since(Instant::now()));
    }
}

#[derive(Clone)]
pub struct FakeTime(Arc<Mutex<FakeTimeState<Sender<()>>>>);

impl FakeTime {
    pub fn advance(&self, d: Duration) {
        self.0.lock().unwrap().advance(d);
    }
    pub fn wait_exact_sleepers_count(&self, count: usize) {
        let (tx, rx) = mpsc::channel();
        let waiter = SleepWaiter { count, signal: tx };
        self.0.lock().unwrap().add_sleep_waiter(waiter);
        rx.recv().unwrap();
    }
}

impl Time for FakeTime {
    fn monotonic_now(&self) -> Instant {
        return self.0.lock().unwrap().monotonic();
    }

    fn system_now(&self) -> SystemTime {
        return self.0.lock().unwrap().real();
    }

    fn sleep(&self, duration: Duration) {
        self.sleep_until(self.monotonic_now().add(duration))
    }

    fn sleep_until(&self, dst: Instant) {
        let (tx, rx) = mpsc::channel::<()>();
        {
            let sleeper = Sleeper {
                monotonic: dst,
                signal: tx,
            };

            self.0.lock().unwrap().add_sleeper(sleeper);
        }
        rx.recv().unwrap();
    }
}

impl Default for FakeTime {
    fn default() -> Self {
        return FakeTime(Arc::new(Mutex::new(FakeTimeState::default())));
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use std::sync::atomic::Ordering::Relaxed;
    use std::sync::atomic::{AtomicBool, Ordering};

    #[test]
    fn test_sleep() {
        let clock = FakeTime::default();
        let dst = clock.monotonic_now().add(Duration::from_secs(60));
        let clock2 = clock.clone();
        let thread_worked = Arc::new(AtomicBool::new(false));
        let thread_worked2 = thread_worked.clone();
        let handler = thread::spawn(move || {
            clock2.sleep_until(dst);
            assert_eq!(dst, clock2.monotonic_now());
            thread_worked2.store(true, Relaxed);
        });

        clock.advance(Duration::from_secs(60));
        handler.join().unwrap();
        assert_eq!(true, thread_worked.load(Relaxed));
    }

    #[test]
    fn test_wait_sleepers() {
        let clock = FakeTime::default();
        let clock2 = clock.clone();
        let dst = clock.monotonic_now().add(Duration::from_secs(60));
        let thread_worked = Arc::new(AtomicBool::new(false));
        let thread_worked2 = thread_worked.clone();
        let handler = thread::spawn(move || {
            clock2.sleep(Duration::from_secs(60));
            assert_eq!(dst, clock2.monotonic_now());
            thread_worked2.store(true, Relaxed);
        });
        clock.wait_exact_sleepers_count(1);
        clock.advance(Duration::from_secs(60));
        handler.join().unwrap();
        assert_eq!(true, thread_worked.load(Relaxed));
    }
}

impl Signal for Sender<()> {
    fn signal(&self) {
        let _ = self.send(());
    }
}