use std::fmt::Debug;
mod annotation;
mod data;
mod dfs;
mod pct;
mod random;
mod replay;
mod round_robin;
mod uncontrolled_nondeterminism;
pub(crate) mod metrics;
pub(crate) mod serialization;
pub use crate::runtime::task::{Task, TaskId};
pub use annotation::AnnotationScheduler;
pub use data::{DataSource, RandomDataSource};
pub use dfs::DfsScheduler;
pub use pct::PctScheduler;
pub use random::RandomScheduler;
pub use replay::ReplayScheduler;
pub use round_robin::RoundRobinScheduler;
pub use uncontrolled_nondeterminism::UncontrolledNondeterminismCheckScheduler;
#[derive(Clone, Debug, Default, PartialEq, Eq)]
pub struct Schedule {
seed: u64,
steps: Vec<ScheduleStep>,
}
#[derive(Clone, Debug, PartialEq, Eq)]
enum ScheduleStep {
Task(TaskId),
Random,
}
impl Schedule {
pub fn new(seed: u64) -> Self {
Self { seed, steps: vec![] }
}
pub fn new_from_task_ids<T>(seed: u64, task_ids: impl IntoIterator<Item = T>) -> Self
where
T: Into<TaskId>,
{
let steps = task_ids
.into_iter()
.map(|t| ScheduleStep::Task(t.into()))
.collect::<Vec<_>>();
Self { seed, steps }
}
pub fn push_task(&mut self, task: TaskId) {
self.steps.push(ScheduleStep::Task(task));
}
pub fn push_random(&mut self) {
self.steps.push(ScheduleStep::Random);
}
pub fn len(&self) -> usize {
self.steps.len()
}
pub fn is_empty(&self) -> bool {
self.steps.is_empty()
}
}
pub trait Scheduler {
fn new_execution(&mut self) -> Option<Schedule>;
fn next_task(
&mut self,
runnable_tasks: &[&Task],
current_task: Option<TaskId>,
is_yielding: bool,
) -> Option<TaskId>;
fn next_u64(&mut self) -> u64;
}
impl Scheduler for Box<dyn Scheduler + Send> {
fn new_execution(&mut self) -> Option<Schedule> {
self.as_mut().new_execution()
}
fn next_task(
&mut self,
runnable_tasks: &[&Task],
current_task: Option<TaskId>,
is_yielding: bool,
) -> Option<TaskId> {
self.as_mut().next_task(runnable_tasks, current_task, is_yielding)
}
fn next_u64(&mut self) -> u64 {
self.as_mut().next_u64()
}
}