use crate::{Error, Interval, Target};
use async_std::{
sync::{Arc, Barrier},
task,
};
use std::{collections::BTreeMap, hash::Hash};
pub struct ClockCtrl<K>
where
K: Hash + Ord,
{
clocks: BTreeMap<K, Target>,
}
pub enum Scheduler {
Internal(Arc<Barrier>),
External {
delay: f32,
a: Arc<Barrier>,
b: Arc<Barrier>,
},
}
impl<K> ClockCtrl<K>
where
K: Hash + Ord,
{
pub fn new() -> Self {
Self {
clocks: Default::default(),
}
}
pub fn setup(&mut self, trgt: K) -> &mut Target {
self.clocks.entry(trgt).or_insert(Target::default())
}
pub fn start(&mut self, target: K) -> Result<Scheduler, Error> {
let b = Arc::new(Barrier::new(2));
match self.clocks.remove(&target) {
Some(Target { interval, fence }) => match (interval, fence) {
(None, None) => Ok(Scheduler::External {
delay: 1.0,
a: Arc::clone(&b),
b,
}),
(Some(Interval::Delay(d)), None) => Ok(Scheduler::External {
delay: d,
a: Arc::clone(&b),
b,
}),
(Some(Interval::Timed(dur)), None) => {
let a = Arc::clone(&b);
task::spawn(async move {
loop {
task::sleep(dur).await;
a.wait().await;
}
});
Ok(Scheduler::Internal(b))
}
(Some(Interval::Stepped), Some(fence)) => {
let a = Arc::clone(&b);
task::spawn(async move {
fence(a);
});
Ok(Scheduler::Internal(b))
},
(_, _) => panic!("Invalid scheduler setup"),
},
None => Err(Error::NoTarget),
}
}
}