use crate::TimeSpan;
#[doc = crate::_tags!(runtime time)]
#[doc = crate::_doc_meta!{location("run/time")}]
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct RunPacer<T: TimeSpan> {
interval: T,
accum: T,
}
impl<T: TimeSpan> RunPacer<T> {
pub fn new(interval: T) -> Option<Self> {
if interval.time_is_zero() {
None
} else {
Some(Self { interval, accum: T::TIME_ZERO })
}
}
pub const fn interval(&self) -> T {
self.interval
}
pub const fn accum(&self) -> T {
self.accum
}
pub fn allow(&mut self, dt: T) -> bool {
self.allow_checked(dt).expect("RunPacer span arithmetic overflowed or underflowed")
}
pub fn allow_checked(&mut self, dt: T) -> Option<bool> {
self.accum = self.accum.time_add_checked(dt)?;
if self.accum >= self.interval {
self.accum = self.accum.time_sub_checked(self.interval)?;
Some(true)
} else {
Some(false)
}
}
pub fn cycles(&mut self, dt: T) -> u64 {
self.cycles_checked(dt).expect("RunPacer span arithmetic overflowed or underflowed")
}
pub fn cycles_checked(&mut self, dt: T) -> Option<u64> {
self.accum = self.accum.time_add_checked(dt)?;
let mut cycles = 0_u64;
while self.accum >= self.interval {
self.accum = self.accum.time_sub_checked(self.interval)?;
cycles = cycles.checked_add(1)?;
}
Some(cycles)
}
}