use crate::alloc::boxed::Box;
use crate::private::ringq::RingQ;
use crate::event::{OxideEvent, EventSink, EventSource, OxideEventEnvelope};
use crate::hal::concurrency::interrupt;
pub struct OxideSupervisor<'e>
{
event_q: RingQ<OxideEventEnvelope<'e>, 16>,
}
static mut GLOBAL_INSTANCE : Option<&mut OxideSupervisor> = None;
pub(crate) fn create_supervisor<'a>() -> OxideSupervisor<'a> {
OxideSupervisor {
event_q: RingQ::new_with(OxideEventEnvelope::anon(OxideEvent::Initialise)),
}
}
pub(crate) unsafe fn set_global_supervisor(global: &mut OxideSupervisor) {
GLOBAL_INSTANCE.replace(core::mem::transmute(global));
}
pub fn instance() -> &'static mut OxideSupervisor<'static> {
unsafe {
match &mut GLOBAL_INSTANCE {
Some(instance) => {
*instance
},
None => panic!()
}
}
}
impl OxideSupervisor<'_> {
#[cfg(feature="alloc_ftr")]
pub fn listen<EP: 'static + EventSource>(&mut self, source: Box<EP>) {
let source : &'static mut EP = Box::leak(source);
source.listen();
}
pub fn listen_byref<EP: 'static + EventSource>(&mut self, source: &'static EP) {
source.listen();
}
pub fn run_with_prehandler<F: FnMut(OxideEvent) -> bool>(&mut self, mut pre_handler: F) -> ! {
loop {
interrupt::wait();
while let Some(event) = self.event_q.consume_nolock() {
if pre_handler(event.unwrap()) {
event.invoke_recipient();
}
}
}
}
pub fn run(&mut self) -> ! {
self.run_with_prehandler(|_|{true});
}
}
impl EventSink for OxideSupervisor<'_> {
fn event(event: OxideEventEnvelope) {
unsafe {
match &mut GLOBAL_INSTANCE {
None => {}
Some(supervisor) => {
let _ = (*supervisor).event_q.append_nolock(core::mem::transmute(event));
}
}
}
}
}