use crate::{Clock, Signal, paused};
use std::sync::atomic::Ordering;
use std::sync::mpsc::{self, Receiver, SyncSender};
use std::sync::{Arc, Mutex};
use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH};
pub(crate) fn blocked(clock: &Clock) -> usize {
clock.paused.as_ref().unwrap().state.lock().unwrap().blocked
}
pub(crate) fn wakes(signal: &Signal) -> usize {
signal.wakes.load(Ordering::SeqCst)
}
pub(crate) fn signals(clock: &Clock) -> Vec<Arc<Signal>> {
clock
.paused
.as_ref()
.unwrap()
.state
.lock()
.unwrap()
.signals
.values()
.map(|signal| signal.upgrade().expect("registered signal is live"))
.collect()
}
pub(crate) fn pause_before_park(clock: &Clock) -> (Receiver<Option<Instant>>, SyncSender<()>) {
pause(&clock.paused.as_ref().unwrap().before_park)
}
pub(crate) fn pause_before_rewait(clock: &Clock) -> (Receiver<Option<Instant>>, SyncSender<()>) {
pause(&clock.paused.as_ref().unwrap().before_rewait)
}
fn pause(hook: &Mutex<Option<paused::BeforePark>>) -> (Receiver<Option<Instant>>, SyncSender<()>) {
let (checked, checks) = mpsc::sync_channel(0);
let (resume, resumed) = mpsc::sync_channel(0);
*hook.lock().unwrap() = Some(Box::new(move |timer| {
checked.send(timer).unwrap();
resumed.recv().unwrap();
}));
(checks, resume)
}
pub(crate) fn last_system_time() -> SystemTime {
let mut time = UNIX_EPOCH;
for bit in (0..64).rev() {
if let Some(next) = time.checked_add(Duration::from_secs(1 << bit)) {
time = next;
}
}
time
}