use crate::{
ManualMonotonicClock,
MonotonicClock,
MonotonicInstant,
WallClock,
};
use std::sync::{
Arc,
Mutex,
MutexGuard,
};
use std::time::SystemTime;
#[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")
}
}