use std::sync::Arc;
use std::sync::Mutex;
use std::time::{Duration, Instant};
use crate::bus::LogicalTime;
pub trait ClockSource: Send + Sync + 'static {
fn now(&self) -> LogicalTime;
}
pub struct RealClock {
epoch: u64,
start: Instant,
}
impl RealClock {
pub fn new() -> Self {
RealClock {
epoch: 0,
start: Instant::now(),
}
}
}
impl Default for RealClock {
fn default() -> Self {
RealClock::new()
}
}
impl ClockSource for RealClock {
fn now(&self) -> LogicalTime {
let ns = u64::try_from(self.start.elapsed().as_nanos()).unwrap_or(u64::MAX);
LogicalTime::new(self.epoch, ns)
}
}
#[derive(Clone)]
pub struct TestClock {
state: Arc<Mutex<(u64, u64)>>, }
impl TestClock {
pub fn new() -> Self {
TestClock {
state: Arc::new(Mutex::new((0, 0))),
}
}
pub fn advance(&self, delta: Duration) {
let mut state = self.state.lock().expect("test clock poisoned");
let ns = u64::try_from(delta.as_nanos()).unwrap_or(u64::MAX);
state.1 = state.1.saturating_add(ns);
}
pub fn bump_epoch(&self) {
let mut state = self.state.lock().expect("test clock poisoned");
state.0 = state.0.saturating_add(1);
state.1 = 0;
}
}
impl Default for TestClock {
fn default() -> Self {
TestClock::new()
}
}
impl ClockSource for TestClock {
fn now(&self) -> LogicalTime {
let state = self.state.lock().expect("test clock poisoned");
LogicalTime::new(state.0, state.1)
}
}