1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
//! Clocks providing Instants to this library
//!
//! Instants (i.e. time points) can come from various sources. The Rust stdlib
//! is one of them, but we expect to add more in the future, which provide
//! additional performance and/or correctness on specific systems.

#[cfg(target_os = "linux")]
pub mod linux;
mod std;

use crate::Instant;

// Reexport the StdClock, there is no point exporting the whole std module as
// it's the only thing inside of it.
pub use self::std::StdClock;

/// Common interface shared by all Clocks provided by this library
pub trait Clock: Default {
    /// Get an Instant representing the current time
    ///
    /// Instants should be above `Instant::EPOCH` and monotonically increasing,
    /// but low-quality clocks may slow down and speed up slightly as they try
    /// to synchronize themselves with other clocks. Good timestamp clocks will
    /// prevent this and always deliver 100% steady time.
    ///
    fn now(&self) -> Instant;
}

/// Recommended choice of Clock for your system
#[cfg(not(target_os = "linux"))]
pub type DefaultClock = StdClock;

/// Recommended choice of Clock for Linux systems
#[cfg(target_os = "linux")]
pub type DefaultClock = linux::BootTimeClock;

#[cfg(test)]
pub(crate) mod tests {
    use super::*;
    use crate::{Clock, Duration, Instant};

    /// Generic test for a Clock
    pub(crate) fn generic_clock_test<C: Clock>() {
        // Default-construct a clock
        let clock = C::default();

        // First time point
        let t1 = clock.now();
        assert!(t1 >= Instant::EPOCH);
        assert!(t1 < Instant::SOMEDAY);

        // Second time point
        let t2 = clock.now();
        assert!(t2 >= t1);
        assert!(t2 < Instant::SOMEDAY);

        // Any self-respecting clock should have at least millisecond resolution
        ::std::thread::sleep(::std::time::Duration::from_millis(2));
        let t3 = clock.now();
        assert!(t3 > t2 + Duration::MILLISECOND);
        assert!(t3 < Instant::SOMEDAY);
    }

    /// Test the default clock in this way
    #[test]
    fn default_clock() {
        generic_clock_test::<DefaultClock>();
    }
}