2024-10-27 11:19:26 +01:00
|
|
|
use std::fmt;
|
|
|
|
|
|
|
|
pub trait Task {
|
|
|
|
fn tick(&mut self) {}
|
|
|
|
fn start(&mut self) {}
|
|
|
|
fn stop(&mut self) {}
|
2024-11-02 15:18:15 +01:00
|
|
|
fn name(&self) -> &'static str {
|
|
|
|
core::any::type_name::<Self>()
|
|
|
|
}
|
2024-10-27 11:19:26 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
trait ScheduledState: std::fmt::Debug {
|
|
|
|
fn start(self: Box<Self>) -> Box<dyn ScheduledState>;
|
|
|
|
fn stop(self: Box<Self>) -> Box<dyn ScheduledState>;
|
|
|
|
fn tick(self: Box<Self>, task: &mut dyn Task) -> Box<dyn ScheduledState>;
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
struct Starting {}
|
|
|
|
impl ScheduledState for Starting {
|
|
|
|
fn start(self: Box<Self>) -> Box<dyn ScheduledState> {
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
|
|
|
fn stop(self: Box<Self>) -> Box<dyn ScheduledState> {
|
|
|
|
Box::new(Stopped {})
|
|
|
|
}
|
|
|
|
|
|
|
|
fn tick(self: Box<Self>, task: &mut dyn Task) -> Box<dyn ScheduledState> {
|
|
|
|
task.start();
|
|
|
|
Box::new(Running{})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
struct Running {}
|
|
|
|
impl ScheduledState for Running {
|
|
|
|
fn start(self: Box<Self>) -> Box<dyn ScheduledState> {
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
|
|
|
fn stop(self: Box<Self>) -> Box<dyn ScheduledState> {
|
|
|
|
Box::new(Stopping {})
|
|
|
|
}
|
|
|
|
|
|
|
|
fn tick(self: Box<Self>, task: &mut dyn Task) -> Box<dyn ScheduledState> {
|
|
|
|
task.tick();
|
|
|
|
self
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
struct Stopping {}
|
|
|
|
impl ScheduledState for Stopping {
|
|
|
|
fn start(self: Box<Self>) -> Box<dyn ScheduledState> {
|
|
|
|
Box::new(Running {})
|
|
|
|
}
|
|
|
|
|
|
|
|
fn stop(self: Box<Self>) -> Box<dyn ScheduledState> {
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
|
|
|
fn tick(self: Box<Self>, task: &mut dyn Task) -> Box<dyn ScheduledState> {
|
|
|
|
task.stop();
|
|
|
|
Box::new(Stopped {})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
struct Stopped {}
|
|
|
|
impl ScheduledState for Stopped {
|
|
|
|
fn start(self: Box<Self>) -> Box<dyn ScheduledState> {
|
|
|
|
Box::new(Starting {})
|
|
|
|
}
|
|
|
|
|
|
|
|
fn stop(self: Box<Self>) -> Box<dyn ScheduledState> {
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
|
|
|
fn tick(self: Box<Self>, _task: &mut dyn Task) -> Box<dyn ScheduledState> {
|
|
|
|
self
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
struct ScheduledTask {
|
|
|
|
state: Option<Box<dyn ScheduledState>>,
|
2024-10-27 15:14:28 +01:00
|
|
|
task: Box<dyn Task>,
|
2024-10-27 11:19:26 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
impl std::fmt::Debug for ScheduledTask {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
|
|
f.debug_struct("ScheduledTask")
|
|
|
|
.field("task", &self.task.name())
|
|
|
|
.field("state", &self.state)
|
|
|
|
.finish()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl ScheduledTask {
|
|
|
|
fn new(task: Box<dyn Task>) -> Self {
|
|
|
|
ScheduledTask {
|
|
|
|
state: Some(Box::new(Starting{})),
|
2024-10-27 15:14:28 +01:00
|
|
|
task: task,
|
2024-10-27 11:19:26 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn start(&mut self) {
|
|
|
|
if let Some(s) = self.state.take() {
|
|
|
|
self.state = Some(s.start());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn stop(&mut self) {
|
|
|
|
if let Some(s) = self.state.take() {
|
|
|
|
self.state = Some(s.stop());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn tick(&mut self) {
|
|
|
|
if let Some(s) = self.state.take() {
|
|
|
|
self.state = Some(s.tick(self.task.as_mut()));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct Scheduler {
|
2024-10-27 15:14:28 +01:00
|
|
|
tasks: Vec<ScheduledTask>,
|
2024-10-27 11:19:26 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Scheduler {
|
|
|
|
pub fn new(tasks: Vec<Box<dyn Task>>) -> Self {
|
|
|
|
let mut scheduled = Vec::new();
|
|
|
|
for task in tasks {
|
|
|
|
log::info!("Scheduling task {:?}", task.name());
|
|
|
|
scheduled.push(ScheduledTask::new(task));
|
|
|
|
}
|
|
|
|
Scheduler {
|
|
|
|
tasks: scheduled
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn tick(&mut self) {
|
|
|
|
for task in &mut self.tasks {
|
|
|
|
task.tick();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|