use super::*;
pub struct SimulationTimer {
time: u128,
timer: QuadWheelWithOverflow,
}
impl SimulationTimer {
pub fn new() -> SimulationTimer {
SimulationTimer {
time: 0u128,
timer: QuadWheelWithOverflow::new(),
}
}
pub fn at(now: SystemTime) -> SimulationTimer {
let t = now
.duration_since(SystemTime::UNIX_EPOCH)
.expect("SystemTime before UNIX EPOCH!");
let tms = t.as_millis();
SimulationTimer {
time: tms,
timer: QuadWheelWithOverflow::new(),
}
}
pub fn current_time(&self) -> u128 {
self.time
}
pub fn next(&mut self) -> SimulationStep {
loop {
match self.timer.can_skip() {
Skip::Empty => return SimulationStep::Finished,
Skip::None => {
let mut res = self.timer.tick();
self.time += 1u128;
if !res.is_empty() {
for e in res.drain(..) {
e.execute();
}
return SimulationStep::Ok;
}
}
Skip::Millis(ms) => {
self.timer.skip(ms);
self.time += ms as u128;
let mut res = self.timer.tick();
self.time += 1u128;
if !res.is_empty() {
for e in res.drain(..) {
e.execute();
}
return SimulationStep::Ok;
}
}
}
}
}
}
pub enum SimulationStep {
Finished,
Ok,
}
impl Timer for SimulationTimer {
fn schedule_once<F>(&mut self, id: Uuid, timeout: Duration, action: F) -> ()
where
F: FnOnce(Uuid) + Send + 'static,
{
let e = TimerEntry::OneShot {
id,
timeout,
action: Box::new(action),
};
match self.timer.insert(e) {
Ok(_) => (), Err(TimerError::Expired(e)) => {
if let None = e.execute() {
()
} else {
panic!("OneShot produced reschedule!")
} }
Err(f) => panic!("Could not insert timer entry! {:?}", f),
}
}
fn schedule_periodic<F>(&mut self, id: Uuid, delay: Duration, period: Duration, action: F) -> ()
where
F: Fn(Uuid) + Send + 'static,
{
let e = TimerEntry::Periodic {
id,
delay,
period,
action: Box::new(action),
};
match self.timer.insert(e) {
Ok(_) => (), Err(TimerError::Expired(e)) => match e.execute() {
Some(new_e) => match self.timer.insert(new_e) {
Ok(_) => (), Err(TimerError::Expired(e)) => panic!(
"Trying to insert periodic timer entry with 0ms period! {:?}",
e
),
Err(f) => panic!("Could not insert timer entry! {:?}", f),
},
None => unreachable!(), },
Err(f) => panic!("Could not insert timer entry! {:?}", f),
}
}
fn cancel(&mut self, id: Uuid) {
match self.timer.cancel(id) {
Ok(_) => (), Err(f) => eprintln!("Could not cancel timer with id={}. {:?}", id, f), }
}
}