use parking_lot::Mutex;
use std::sync::Arc;
use std::time::{Duration, Instant};
#[derive(Clone)]
pub(crate) struct RuntimeClock {
pub(super) now: Arc<Mutex<Instant>>,
}
impl RuntimeClock {
pub(crate) fn now(&self) -> Instant {
*self.now.lock()
}
pub(crate) fn set_now(&self, now: Instant) {
*self.now.lock() = now;
}
}
pub trait AdvanceClock {
fn advance_clock(&self, now: Instant, next_timer_elapsed: Instant) -> Instant;
}
impl AdvanceClock for AdvanceToNextWake {
fn advance_clock(&self, _now: Instant, next_timer_elapsed: Instant) -> Instant {
next_timer_elapsed
}
}
impl AdvanceClock for AdvanceToNextWakeWithGranularity {
fn advance_clock(&self, now: Instant, next_timer_elapsed: Instant) -> Instant {
let last_time_jump = self.last_time_jump_to.lock().unwrap_or(now);
let diff = next_timer_elapsed - last_time_jump;
let elapsed_intervals =
(self.clock_granularity.as_secs_f64() / diff.as_secs_f64()).ceil() as u32;
let new_time = now + self.clock_granularity * elapsed_intervals;
*self.last_time_jump_to.lock() = Some(new_time);
new_time
}
}
pub struct AdvanceToNextWake;
pub struct AdvanceToNextWakeWithGranularity {
last_time_jump_to: Mutex<Option<Instant>>,
clock_granularity: Duration,
}
impl AdvanceToNextWakeWithGranularity {
pub fn new(clock_granularity: Duration) -> Self {
Self {
last_time_jump_to: Mutex::default(),
clock_granularity,
}
}
}