cap_time_ext/
monotonic_clock.rs

1#[cfg(not(windows))]
2use rustix::time::{clock_getres, ClockId};
3use std::time;
4use std::time::Duration;
5#[cfg(windows)]
6use {once_cell::sync::Lazy, winx::time::perf_counter_frequency};
7
8/// Extension trait for `cap_std::time::MonotonicClock`.
9pub trait MonotonicClockExt {
10    /// A monotonic clock datapoint.
11    type Instant;
12
13    /// Similar to `MonotonicClock::now`, but takes an additional `precision`
14    /// parameter allowing callers to inform the implementation when they
15    /// don't need full precision. The implementation need not make any
16    /// effort to provide a time with greater precision.
17    fn now_with(&self, precision: Duration) -> Self::Instant;
18
19    /// Return the resolution of the clock.
20    fn resolution(&self) -> Duration;
21}
22
23#[cfg(not(windows))]
24impl MonotonicClockExt for cap_primitives::time::MonotonicClock {
25    type Instant = cap_primitives::time::Instant;
26
27    #[cfg(not(target_os = "wasi"))]
28    #[inline]
29    fn now_with(&self, _precision: Duration) -> Self::Instant {
30        // On systems with no optimized form of `clock_gettime`, ignore the
31        // precision argument.
32        Self::Instant::from_std(time::Instant::now())
33    }
34
35    fn resolution(&self) -> Duration {
36        let spec = clock_getres(ClockId::Realtime);
37        Duration::new(
38            spec.tv_sec.try_into().unwrap(),
39            spec.tv_nsec.try_into().unwrap(),
40        )
41    }
42}
43
44#[cfg(windows)]
45impl MonotonicClockExt for cap_primitives::time::MonotonicClock {
46    type Instant = cap_primitives::time::Instant;
47
48    #[inline]
49    fn now_with(&self, _precision: Duration) -> Self::Instant {
50        // On systems with no optimized form of `clock_gettime`, ignore the
51        // precision argument.
52        Self::Instant::from_std(time::Instant::now())
53    }
54
55    fn resolution(&self) -> Duration {
56        Duration::new(0, (*PERF_COUNTER_RES).try_into().unwrap())
57    }
58}
59
60#[cfg(windows)]
61static PERF_COUNTER_RES: Lazy<u64> =
62    Lazy::new(|| 1_000_000_000 / perf_counter_frequency().unwrap());