extern crate std;
use crate::{
simulator::Config,
traits::{AsyncInput, Bag},
};
use std::{
thread,
time::{Duration, Instant, SystemTime},
};
pub fn sleep<T: Bag>(config: &Config) -> impl FnMut(f64, f64, &mut T) -> f64 {
wait_event(config, |waiting_period, _| thread::sleep(waiting_period))
}
pub fn wait_event<T: Bag>(
config: &Config,
mut input_handler: impl FnMut(Duration, &mut T),
) -> impl FnMut(f64, f64, &mut T) -> f64 {
let (time_scale, max_jitter) = (config.time_scale, config.max_jitter);
let mut last_rt = SystemTime::now();
let start_rt = last_rt;
move |t_from, t_until, binput: &mut T| -> f64 {
let next_rt = last_rt + Duration::from_secs_f64((t_until - t_from) * time_scale);
if let Ok(duration) = next_rt.duration_since(SystemTime::now()) {
input_handler(duration, binput);
}
let t = SystemTime::now();
match t.duration_since(next_rt) {
Ok(duration) => {
if let Some(max_jitter) = max_jitter {
if duration > max_jitter {
panic!("[WE]>> Jitter too high: {:?}", duration);
}
}
last_rt = next_rt;
t_until
}
Err(_) => {
last_rt = t;
let duration = last_rt.duration_since(start_rt).unwrap();
duration.as_secs_f64() / time_scale
}
}
}
}
#[derive(Default)]
pub struct SleepAsync<T: Bag> {
last_rt: Option<Instant>,
input: core::marker::PhantomData<T>,
}
impl<T: Bag> SleepAsync<T> {
pub fn new() -> Self {
Self {
last_rt: None,
input: core::marker::PhantomData,
}
}
}
impl<T: Bag> AsyncInput for SleepAsync<T> {
type Input = T;
async fn handle(
&mut self,
config: &Config,
t_from: f64,
t_until: f64,
_input: &mut Self::Input,
) -> f64 {
let last_rt = self.last_rt.unwrap_or_else(Instant::now);
let next_rt = last_rt + Duration::from_secs_f64((t_until - t_from) * config.time_scale);
tokio::time::sleep_until(next_rt.into()).await;
self.last_rt = Some(next_rt);
t_until
}
}