mod queue;
mod waker;
pub(crate) use queue::ScheduledWaker;
pub(crate) use waker::make_waker;
use std::cmp::Reverse;
use std::collections::BinaryHeap;
use std::future::Future;
use std::pin::Pin;
use std::sync::{Arc, Mutex};
use std::task::Waker;
pub(crate) struct ProcessEntry {
pub future: Pin<Box<dyn Future<Output = ()>>>,
pub waker: Waker,
}
pub(crate) struct SimState {
pub current_time: f64,
pub event_queue: BinaryHeap<Reverse<ScheduledWaker>>,
pub seq_counter: u64,
pub ready_queue: Arc<Mutex<Vec<usize>>>,
pub next_process_id: usize,
pub processes: Vec<Option<ProcessEntry>>,
#[allow(clippy::type_complexity)]
pub pending_spawns: Vec<(usize, Pin<Box<dyn Future<Output = ()>>>)>,
}
impl SimState {
pub fn new() -> Self {
SimState {
current_time: 0.0,
event_queue: BinaryHeap::new(),
seq_counter: 0,
ready_queue: Arc::new(Mutex::new(Vec::new())),
next_process_id: 0,
processes: Vec::new(),
pending_spawns: Vec::new(),
}
}
pub fn schedule_wakeup(&mut self, time: f64, waker: std::task::Waker) {
debug_assert!(
time.is_finite() && time >= self.current_time,
"schedule_wakeup time must be finite and not in the past"
);
let seq = self.seq_counter;
self.seq_counter += 1;
self.event_queue.push(Reverse(ScheduledWaker { time, seq, waker }));
}
pub fn alloc_process_id(&mut self) -> usize {
let id = self.next_process_id;
self.next_process_id += 1;
id
}
}