use std::time::Instant;
use std::rc::Rc;
use std::cell::RefCell;
use crate::TimerBox;
use crate::timer_box;
pub trait Timer {
fn start(&mut self);
fn finish(&mut self) -> i64;
fn hz(&self) -> u128; }
#[derive(Clone)]
pub struct DurationTimer {
start: Instant,
previous: u128,
}
impl Timer for DurationTimer {
fn start(&mut self) {
self.start = Instant::now();
self.previous = 0;
}
fn finish(&mut self) -> i64 {
let end_time = self.start.elapsed().as_nanos();
let result = end_time - self.previous;
self.previous = end_time;
std::cmp::min(result, i64::MAX as u128) as i64
}
fn hz(&self) -> u128 {
1_000_000_000
}
}
impl DurationTimer {
pub fn new() -> DurationTimer {
let start = Instant::now();
let previous = 0;
DurationTimer { start, previous }
}
pub fn new_box() -> TimerBox {
let timer = DurationTimer::new();
timer_box!(timer)
}
}
impl Default for DurationTimer {
fn default() -> Self {
Self::new()
}
}
pub trait SimpleClock {
fn get_time(&mut self) -> u128;
fn hz(&self) -> u128;
}
#[derive(Clone)]
pub struct ClockTimer {
start: u128,
clock: Rc<RefCell<dyn SimpleClock>>,
hz: u128,
}
impl Timer for ClockTimer {
fn start(&mut self) {
self.start = self.clock.borrow_mut().get_time();
}
fn finish(&mut self) -> i64 {
let end_time = self.clock.borrow_mut().get_time();
let ticks = end_time - self.start;
self.start = end_time;
ticks as i64
}
fn hz(&self) -> u128 {
self.hz
}
}
impl ClockTimer {
pub fn new(clock: Rc<RefCell<dyn SimpleClock>>) -> ClockTimer {
let start = clock.borrow_mut().get_time();
let hz = clock.borrow().hz();
ClockTimer { start, clock, hz }
}
pub fn new_box(clock: Rc<RefCell<dyn SimpleClock>>) -> TimerBox {
let timer = ClockTimer::new(clock);
timer_box!(timer)
}
}
#[macro_export]
macro_rules! timer_box { ($x:expr) => { Rc::from(RefCell::new($x)) } }
#[macro_export]
macro_rules! timer { ($x:expr) => { &*$x.borrow() } }
#[macro_export]
macro_rules! timer_mut { ($x:expr) => { &mut *$x.borrow_mut() } }
#[cfg(test)]
pub mod tests {
use super::*;
use std::thread::sleep;
use std::time::Duration;
fn simple_duration_test() {
let mut clock = DurationTimer::new();
let seconds = 1;
let sleep_time = Duration::new(seconds, 0);
let base_interval = seconds as i64 * clock.hz() as i64;
clock.start();
for _i in 1..10 {
sleep(sleep_time);
let interval = clock.finish();
assert!(interval >= base_interval);
assert!(interval < base_interval + (base_interval / 20));
}
}
pub struct TestSimpleClock {
pub current: u128,
pub increment: u128,
}
impl SimpleClock for TestSimpleClock {
fn get_time(&mut self) -> u128 {
let result = self.current;
self.current = self.current + self.increment;
result
}
fn hz(&self) -> u128 {
1_000_000_000
}
}
pub fn simple_test_clock() {
let current = 0;
let increment = 1500;
let simple_clock = timer_box!(TestSimpleClock { current, increment });
let clock = ClockTimer::new_box(simple_clock);
let clock = timer_mut!(clock);
assert!(clock.hz() == 1_000_000_000);
clock.start();
for _i in 1..5 {
let interval = clock.finish();
assert!(interval == increment as i64);
}
}
struct ExampleClock {
current_time: u128,
hz: u128,
}
impl ExampleClock {
fn new(start_time: u128, hz: u128) -> ExampleClock {
let current_time = start_time;
ExampleClock { current_time, hz }
}
}
impl SimpleClock for ExampleClock {
fn get_time(&mut self) -> u128 {
self.current_time += 1;
self.current_time
}
fn hz(&self) -> u128 {
self.hz
}
}
fn sample_usage() {
let start_time = 1;
let hz = 1_000_000_000;
let mut clock = ExampleClock::new(start_time, hz);
for i in 1..100 {
let time = clock.get_time();
assert!(time == start_time + i);
}
assert!(clock.hz() == hz);
}
fn simple_default_test() {
let mut timer = DurationTimer::default();
for _i in 1..100 {
let nanoseconds = timer.finish();
assert!(nanoseconds >= 0)
}
}
#[test]
pub fn run_tests() {
simple_duration_test();
simple_default_test ();
simple_test_clock ();
sample_usage ();
}
}