Files
renderbug/src/task.rs

150 lines
4.2 KiB
Rust

use core::fmt;
use crate::events::{Event, EventBus, Variant};
pub trait Task: Send {
fn on_ready(&mut self, bus: &mut EventBus) {}
fn on_tick(&mut self, bus: &mut EventBus) {}
fn on_property_change(&mut self, key: &'static str, value: &Variant, bus: &mut EventBus) {}
fn start(&mut self, bus: &mut EventBus) {}
fn stop(&mut self, bus: &mut EventBus) {}
fn name(&self) -> &'static str {
core::any::type_name::<Self>()
}
}
#[derive(Debug, Clone)]
enum ScheduledState {
Stopped,
Start,
Running,
Stop
}
struct ScheduledTask {
state: ScheduledState,
task: Box<dyn Task>,
}
impl core::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: ScheduledState::Stopped,
task: task,
}
}
fn start(&mut self) {
match self.state {
ScheduledState::Stopped => self.state = ScheduledState::Start,
ScheduledState::Stop => self.state = ScheduledState::Running,
_ => ()
}
}
fn stop(&mut self) {
match self.state {
ScheduledState::Running => self.state = ScheduledState::Stop,
ScheduledState::Start => self.state = ScheduledState::Stopped,
_ => ()
}
}
fn tick(&mut self, event: &Event, bus: &mut EventBus) {
match self.state {
ScheduledState::Start => {
log::info!("Starting task {}", self.task.name());
self.task.start(bus);
self.state = ScheduledState::Running
},
ScheduledState::Stop => {
log::info!("Stopping task {}", self.task.name());
self.task.stop(bus);
self.state = ScheduledState::Stopped
},
_ => ()
};
match self.state {
ScheduledState::Running => {
match event {
Event::Tick => self.task.on_tick(bus),
Event::ReadyToRock => self.task.on_ready(bus),
Event::PropertyChange(key, value) => self.task.on_property_change(key, value, bus),
_ => ()
}
},
_ => ()
}
}
}
#[derive(Debug)]
pub struct FixedSizeScheduler<const TASK_COUNT: usize> {
tasks: [ScheduledTask; TASK_COUNT],
}
impl<const TASK_COUNT: usize> FixedSizeScheduler<TASK_COUNT> {
pub fn new(tasks: [Box<dyn Task>; TASK_COUNT]) -> Self {
let mut scheduled: [ScheduledTask; TASK_COUNT] = unsafe { std::mem::MaybeUninit::zeroed().assume_init() };
let mut idx = 0;
for task in tasks {
log::info!("Scheduling task {}", task.name());
let slot = &mut scheduled[idx];
unsafe { std::ptr::write(slot, ScheduledTask::new(task)) };
idx += 1;
}
FixedSizeScheduler {
tasks: scheduled
}
}
fn find_task(&mut self, name: &str) -> Option<&mut ScheduledTask> {
for slot in &mut self.tasks {
if slot.task.name() == name {
return Some(slot);
}
}
None
}
}
impl<const TASK_COUNT: usize> Scheduler for FixedSizeScheduler<TASK_COUNT> {
fn tick(&mut self, event: &Event, bus: &mut EventBus) {
match event {
Event::StartThing(task_name) => {
if let Some(slot) = self.find_task(task_name) {
log::debug!("Starting {}", task_name);
slot.start();
}
},
Event::StopThing(task_name) => {
if let Some(slot) = self.find_task(task_name) {
log::debug!("Stopping {}", task_name);
slot.stop();
}
},
_ => {
for slot in &mut self.tasks {
slot.tick(event, bus);
}
}
}
}
}
pub trait Scheduler {
fn tick(&mut self, event: &Event, bus: &mut EventBus);
}