use crate::{schedule::Schedule, AsyncTask, Task};
cfg_feature! {
"tokio",
mod tokio_scheduler;
}
pub struct Scheduler {
flavour: SchedulerFlavour,
next_identifier: TaskIdentifier,
in_use_ids: Vec<TaskIdentifier>,
}
enum SchedulerFlavour {
#[cfg(feature = "tokio")]
Tokio(tokio_scheduler::TokioScheduler),
}
impl Scheduler {
fn from_flavour(flavour: impl Into<SchedulerFlavour>) -> Self {
Self {
flavour: flavour.into(),
next_identifier: Default::default(),
in_use_ids: Default::default(),
}
}
pub fn add_sync_task<T: Send + 'static>(
&mut self,
task: impl Task<T> + Send + Sync + 'static,
schedule: impl Schedule<T> + Send + 'static,
) -> TaskIdentifier {
let next_id = self.next_identifier;
#[cfg(feature = "log")]
log::info!(
"Registering task [{}] with a TaskIdentifier of [{}].",
std::any::type_name_of_val(&task),
next_id
);
self.next_identifier = self.next_identifier.next();
match &mut self.flavour {
#[cfg(feature = "tokio")]
SchedulerFlavour::Tokio(tok) => tok.add_sync_task(task, schedule, next_id),
};
next_id
}
pub fn add_async_task<T>(
&mut self,
task: impl AsyncTask<T> + Send + Sync + 'static,
schedule: impl Schedule<T> + Send + 'static,
) -> TaskIdentifier
where
T: Send + 'static + Sync,
{
let next_id = self.next_identifier;
#[cfg(feature = "log")]
log::info!(
"Registering task [{}] with a TaskIdentifier of [{}].",
std::any::type_name_of_val(&task),
next_id
);
self.next_identifier = self.next_identifier.next();
match &mut self.flavour {
#[cfg(feature = "tokio")]
SchedulerFlavour::Tokio(tok) => tok.add_async_task(task, schedule, next_id),
};
next_id
}
#[allow(clippy::result_unit_err)]
pub fn cancel_task(&mut self, identifier: TaskIdentifier) -> Result<(), ()> {
let res = match &mut self.flavour {
#[cfg(feature = "tokio")]
SchedulerFlavour::Tokio(tok) => tok.cancel_task(identifier),
};
res.ok_or(())
}
}
impl Drop for Scheduler {
fn drop(&mut self) {
while let Some(id) = self.in_use_ids.pop() {
let _ = self.cancel_task(id);
}
}
}
trait SchedulerExt {
fn add_sync_task<T: Send + 'static>(
&mut self,
task: impl Task<T> + Send + Sync + 'static,
schedule: impl Schedule<T> + Send + 'static,
identifier: TaskIdentifier,
);
fn add_async_task<T: Send + Sync + 'static>(
&mut self,
task: impl AsyncTask<T> + Send + Sync + 'static,
schedule: impl Schedule<T> + Send + 'static,
identifier: TaskIdentifier,
);
fn cancel_task(&mut self, identifier: TaskIdentifier) -> Option<()>;
}
#[derive(Debug, Hash, Eq, PartialEq, Default, Clone, Copy)]
pub struct TaskIdentifier(usize);
impl std::fmt::Display for TaskIdentifier {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_fmt(format_args!("TaskIdentifier({})", self.0))
}
}
impl TaskIdentifier {
fn next(&self) -> Self {
Self(self.0 + 1)
}
}