use std::time::{Duration, Instant};
use crate::Gate;
#[derive(Debug, Clone)]
pub struct Timer {
hz: f64,
dt: Duration,
last_tick: Instant,
next_tick: Instant,
elapsed: Duration,
}
impl Timer {
pub fn from_hz(hz: f64) -> Self {
assert!(
hz.is_finite() && hz > 0.0,
"hz must be finite and greater than zero"
);
let now = Instant::now();
let target_dt = Duration::from_secs_f64(1.0 / hz);
Self {
hz,
dt: Duration::ZERO,
last_tick: now,
next_tick: now + target_dt,
elapsed: Duration::ZERO,
}
}
pub fn hz(&self) -> f64 {
self.hz
}
pub fn dt(&self) -> Duration {
self.dt
}
pub fn elapsed(&self) -> Duration {
self.elapsed
}
pub fn wait(&mut self) {
let target_dt = Duration::from_secs_f64(1.0 / self.hz);
let now = Instant::now();
if now < self.next_tick {
spin_sleep::sleep(self.next_tick - now);
self.next_tick += target_dt;
} else {
self.next_tick = now + target_dt;
}
let tick = Instant::now();
self.dt = tick.duration_since(self.last_tick);
self.elapsed += self.dt;
self.last_tick = tick;
}
pub fn gate(&self, target_hz: f64) -> Gate {
Gate::from_hz(self.hz, target_hz)
}
}