use std::time::Duration; #[cfg(all(not(feature = "test"), target_os = "windows"))] mod inner { pub use std::time::Instant; } #[cfg(all(not(feature = "test"), unix))] #[path = "unix.rs"] mod inner; #[cfg(feature = "test")] mod inner { /// Use mockable time for tests pub use tokio::time::Instant; } const MAX_SLEEP_INTERVAL: Duration = Duration::from_secs(60); /// Represents a measurement of a monotonic clock. /// Unlike [std::time::Instant], the difference between two /// instances is guaranteed to include time spent in system /// sleep. #[derive(Clone, Copy)] pub struct Instant { t: inner::Instant, } impl Instant { pub fn now() -> Self { Self { t: inner::Instant::now(), } } pub fn duration_since(&self, earlier: Instant) -> Duration { self.t.duration_since(earlier.t) } } /// Waits for the specified interval while taking into account system sleep or suspension. /// The accuracy is to within about one minute. pub async fn sleep(duration: Duration) { let started = Instant::now(); loop { let elapsed = Instant::now().duration_since(started); if elapsed >= duration { return; } tokio::time::sleep(std::cmp::min( MAX_SLEEP_INTERVAL, duration.saturating_sub(elapsed), )) .await; } }