#[cfg(feature = "std")]
use core::sync::atomic::{AtomicU64, Ordering};
#[cfg(feature = "std")]
use core::time::Duration;
#[cfg(feature = "std")]
use std::sync::Arc;
#[cfg(feature = "std")]
use std::time::{Instant, SystemTime};
#[cfg(feature = "std")]
use crate::{Monotonic, Wall};
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
pub trait Clock: Send + Sync {
fn now(&self) -> Monotonic;
fn wall(&self) -> Wall;
}
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
#[derive(Debug, Default, Copy, Clone)]
pub struct SystemClock;
#[cfg(feature = "std")]
impl SystemClock {
#[inline]
#[must_use]
pub const fn new() -> Self {
Self
}
}
#[cfg(feature = "std")]
impl Clock for SystemClock {
#[inline]
fn now(&self) -> Monotonic {
Monotonic::now()
}
#[inline]
fn wall(&self) -> Wall {
Wall::now()
}
}
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
#[derive(Debug)]
pub struct ManualClock {
monotonic_anchor: Instant,
wall_anchor: SystemTime,
offset_nanos: AtomicU64,
}
#[cfg(feature = "std")]
impl ManualClock {
#[inline]
#[must_use]
pub fn new() -> Self {
Self {
monotonic_anchor: Instant::now(),
wall_anchor: SystemTime::now(),
offset_nanos: AtomicU64::new(0),
}
}
#[inline]
pub fn advance(&self, by: Duration) {
let nanos = u64::try_from(by.as_nanos()).unwrap_or(u64::MAX);
let _ = self.offset_nanos.fetch_add(nanos, Ordering::Relaxed);
}
#[inline]
#[must_use]
pub fn offset(&self) -> Duration {
Duration::from_nanos(self.offset_nanos.load(Ordering::Relaxed))
}
}
#[cfg(feature = "std")]
impl Default for ManualClock {
#[inline]
fn default() -> Self {
Self::new()
}
}
#[cfg(feature = "std")]
impl Clock for ManualClock {
fn now(&self) -> Monotonic {
let offset = Duration::from_nanos(self.offset_nanos.load(Ordering::Relaxed));
Monotonic(self.monotonic_anchor + offset)
}
fn wall(&self) -> Wall {
let offset = Duration::from_nanos(self.offset_nanos.load(Ordering::Relaxed));
Wall(self.wall_anchor + offset)
}
}
#[cfg(feature = "std")]
impl<C: Clock + ?Sized> Clock for Arc<C> {
#[inline]
fn now(&self) -> Monotonic {
(**self).now()
}
#[inline]
fn wall(&self) -> Wall {
(**self).wall()
}
}
#[cfg(feature = "std")]
impl<C: Clock + ?Sized> Clock for &C {
#[inline]
fn now(&self) -> Monotonic {
(**self).now()
}
#[inline]
fn wall(&self) -> Wall {
(**self).wall()
}
}