use crate::*;
pub struct TickTimeout<T: TickInstant> {
time: T,
timeout: TickDuration<T>,
}
impl<T> TickTimeout<T>
where
T: TickInstant,
{
pub fn nanos(timeout: u32) -> Self {
Self::new(TickDuration::nanos(timeout))
}
pub fn micros(timeout: u32) -> Self {
Self::new(TickDuration::micros(timeout))
}
pub fn millis(timeout: u32) -> Self {
Self::new(TickDuration::millis(timeout))
}
pub fn new(timeout: TickDuration<T>) -> Self {
Self {
time: T::now(),
timeout,
}
}
#[inline]
pub fn timeout(&mut self) -> bool {
if self.time.timeout(&self.timeout) {
self.time.move_forward(&self.timeout);
return true;
}
false
}
#[inline(always)]
pub fn restart(&mut self) {
self.time = T::now();
}
#[inline]
pub fn time_left(&mut self) -> TickDuration<T> {
self.time.time_left(&self.timeout)
}
}
impl<T> From<&TickDuration<T>> for TickTimeout<T>
where
T: TickInstant,
{
fn from(value: &TickDuration<T>) -> Self {
Self::new(value.clone())
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::mock::MockInstant;
use fugit::ExtU32;
#[test]
fn tick_timeout() {
let mut now = MockInstant::now();
assert_eq!(now.elapsed().as_ticks(), 0);
MockInstant::add_time(10.nanos());
assert_eq!(now.elapsed().as_ticks(), 10);
MockInstant::add_time(1.millis());
assert_eq!(now.elapsed().as_ticks(), 1_000_010);
MockInstant::add_time(10.micros());
let mut now2 = MockInstant::now();
assert_eq!(now.elapsed().as_ticks(), 1_010_010);
MockInstant::add_time(10.micros());
assert_eq!(now2.elapsed().as_ticks(), 10_000);
let mut t = TickTimeout::<MockInstant>::nanos(100);
assert!(!t.timeout());
MockInstant::add_time(10.nanos());
assert!(!t.timeout());
MockInstant::add_time(90.nanos());
assert!(t.timeout());
assert!(!t.timeout());
MockInstant::add_time(100.nanos());
assert!(t.timeout());
MockInstant::add_time(90.nanos());
assert!(!t.timeout());
t.restart();
MockInstant::add_time(90.nanos());
assert!(!t.timeout());
MockInstant::add_time(10.nanos());
assert!(t.timeout());
let mut t = TickTimeout::<MockInstant>::micros(100);
assert!(!t.timeout());
MockInstant::add_time(10.micros());
assert!(!t.timeout());
MockInstant::add_time(90.micros());
assert!(t.timeout());
assert!(!t.timeout());
MockInstant::add_time(100.micros());
assert!(t.timeout());
MockInstant::add_time(90.micros());
assert!(!t.timeout());
t.restart();
MockInstant::add_time(90.micros());
assert!(!t.timeout());
MockInstant::add_time(10.micros());
assert!(t.timeout());
let mut t = TickTimeout::<MockInstant>::millis(100);
assert!(!t.timeout());
MockInstant::add_time(10.millis());
assert!(!t.timeout());
MockInstant::add_time(90.millis());
assert!(t.timeout());
assert!(!t.timeout());
MockInstant::add_time(100.millis());
assert!(t.timeout());
MockInstant::add_time(90.millis());
assert!(!t.timeout());
t.restart();
MockInstant::add_time(90.millis());
assert!(!t.timeout());
MockInstant::add_time(10.millis());
assert!(t.timeout());
let mut count = 0;
let dur = TickDuration::<MockInstant>::nanos(100);
let t = MockInstant::now();
assert!(t.timeout_with(&dur, || {
MockInstant::add_time(10.nanos());
count += 1;
true
}));
assert_eq!(count, 10);
let t = TickTimeout::<MockInstant>::micros(40_000_000);
assert_eq!(t.timeout.as_ticks(), 40_000_000_000);
let mut t = TickTimeout::<MockInstant>::millis(40_000);
assert_eq!(t.timeout.as_ticks(), 40_000_000_000);
assert!(!t.timeout());
for _ in 0..40 {
MockInstant::add_time(999.millis());
assert!(!t.timeout());
}
MockInstant::add_time(100.millis());
assert!(t.timeout());
assert!(!t.timeout());
for _ in 0..39 {
MockInstant::add_time(999.millis());
assert!(!t.timeout());
}
t.restart();
for _ in 0..40 {
MockInstant::add_time(999.millis());
assert!(!t.timeout());
}
MockInstant::add_time(100.millis());
assert!(t.timeout());
let dur = TickDuration::<MockInstant>::micros(40_000_000);
let t = TickTimeout::from(&dur);
assert_eq!(t.timeout.as_ticks(), 40_000_000_000);
let t = TickTimeout::new(dur);
assert_eq!(t.timeout.as_ticks(), 40_000_000_000);
}
}
#[cfg(test)]
mod tests_fugit {
use core::ops::Div;
use fugit::{
ExtU32, ExtU32Ceil, KilohertzU32, MicrosDurationU32, MillisDurationU32, NanosDurationU64,
RateExtU32,
};
#[test]
fn duration_tick() {
assert_eq!(1 / 1000, 0);
assert_eq!(1_u32.div(1000), 0);
assert_eq!(1_u32.div_ceil(1000), 1);
let dur: MicrosDurationU32 = 1.micros();
assert_eq!(dur.ticks(), 1);
let dur: MicrosDurationU32 = 1.millis();
assert_eq!(dur.ticks(), 1000);
assert_eq!(dur.to_millis(), 1);
let dur: MillisDurationU32 = 1.millis();
assert_eq!(dur.ticks(), 1);
assert_eq!(dur.to_micros(), 1000);
let dur: MillisDurationU32 = 1.micros();
assert_eq!(dur.ticks(), 0);
let dur: MillisDurationU32 = 1.micros_at_least();
assert_eq!(dur.ticks(), 1);
let dur: MicrosDurationU32 = 1.micros();
assert_eq!(dur.to_millis(), 0);
let dur: MillisDurationU32 = dur.ticks().micros_at_least();
assert_eq!(dur.ticks(), 1);
let a = MicrosDurationU32::micros(100);
let b = MicrosDurationU32::micros(99);
assert!(b < a);
let a = NanosDurationU64::micros(100);
let b = NanosDurationU64::micros(101);
assert!(b > a);
}
#[test]
fn rate_tick() {
let r: KilohertzU32 = 1.MHz();
assert_eq!(r.raw(), 1_000);
let f: u32 = r.to_Hz();
assert_eq!(f, 1_000_000);
}
}