use std::sync::Arc;
use std::sync::Mutex;
use std::sync::MutexGuard;
use std::time::SystemTime;
use crate::ManualMonotonicClock;
use crate::MonotonicClock;
use crate::MonotonicInstant;
use crate::WallClock;
#[derive(Debug)]
pub struct ManualWallClock {
clock: Arc<ManualMonotonicClock>,
anchor: Mutex<(SystemTime, MonotonicInstant)>,
}
impl ManualWallClock {
#[must_use]
#[inline]
pub fn from_clock(wall_time: SystemTime, clock: Arc<ManualMonotonicClock>) -> Self {
let monotonic_anchor = clock.now();
Self {
clock,
anchor: Mutex::new((wall_time, monotonic_anchor)),
}
}
#[inline]
pub fn reanchor(&self, wall_time: SystemTime) {
let mut anchor = self.lock_anchor();
let monotonic_anchor = self.clock.now();
*anchor = (wall_time, monotonic_anchor);
}
#[inline]
fn lock_anchor(&self) -> MutexGuard<'_, (SystemTime, MonotonicInstant)> {
self.anchor.lock().unwrap_or_else(std::sync::PoisonError::into_inner)
}
}
impl WallClock for ManualWallClock {
#[inline]
fn now(&self) -> SystemTime {
let anchor = self.lock_anchor();
let (wall_anchor, monotonic_anchor) = *anchor;
let monotonic_now = self.clock.now();
drop(anchor);
let elapsed = monotonic_now
.duration_since(monotonic_anchor)
.expect("manual wall clock must retain its monotonic clock domain");
wall_anchor
.checked_add(elapsed)
.expect("manual wall time exceeded SystemTime range")
}
}