mod event_holder;
pub(super) mod event_traits;
use crate::{SimState, SimTime};
use event_holder::ScheduledEvent;
use event_traits::Event;
use std::cmp::Reverse;
use std::collections::BinaryHeap;
use std::fmt::{Debug, Formatter};
use std::sync::atomic;
use std::sync::Mutex;
struct BinaryHeapWrapper<State, Time>
where
State: SimState<Time> + Sync,
Time: SimTime + Send + Sync,
{
heap: BinaryHeap<Reverse<ScheduledEvent<State, Time>>>,
}
impl<State, Time> Debug for BinaryHeapWrapper<State, Time>
where
State: SimState<Time> + Sync,
Time: SimTime + Send + Sync,
{
fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
f.debug_list()
.entries(self.heap.iter().map(|holder| &holder.0))
.finish()
}
}
impl<State, Time> Default for BinaryHeapWrapper<State, Time>
where
State: SimState<Time> + Sync,
Time: SimTime + Send + Sync,
{
fn default() -> Self {
Self {
heap: BinaryHeap::default(),
}
}
}
#[derive(Debug, Default)]
pub(super) struct EventQueue<State, Time>
where
State: SimState<Time> + Sync,
Time: SimTime + Send + Sync,
{
events: Mutex<BinaryHeapWrapper<State, Time>>,
events_added: atomic::AtomicUsize,
}
impl<State, Time> EventQueue<State, Time>
where
State: SimState<Time> + Sync,
Time: SimTime + Send + Sync,
{
pub fn new() -> Self {
Self {
events: Mutex::default(),
events_added: atomic::AtomicUsize::new(0),
}
}
pub fn schedule_event(&self, event: Box<dyn Event<State, Time>>, time: Time) {
let mut events_guard = self
.events
.lock()
.expect("event queue mutex should not have been poisoned");
events_guard.heap.push(Reverse(ScheduledEvent {
execution_time: time,
event,
insertion_sequence: self.events_added.fetch_add(1, atomic::Ordering::Relaxed),
}));
}
pub(crate) fn next(&mut self) -> Option<(Box<dyn Event<State, Time>>, Time)> {
if let Some(event_holder) = self
.events
.lock()
.expect("event queue mutex should not have been poisoned")
.heap
.pop()
{
Some((event_holder.0.event, event_holder.0.execution_time))
} else {
None
}
}
}
impl<State, Time> std::fmt::Display for EventQueue<State, Time>
where
State: SimState<Time> + Sync,
Time: SimTime + Send + Sync,
{
fn fmt(&self, formatter: &mut Formatter) -> std::fmt::Result {
write!(
formatter,
"EventQueue with {} scheduled events",
self.events
.lock()
.expect("event queue mutex should not have been poisoned")
.heap
.len(),
)
}
}