#![no_std]
#![doc = include_str!("../README.md")]
use core::sync::atomic::{AtomicUsize, Ordering};
pub type Handler = fn();
pub struct HandlerTable<const N: usize> {
handlers: [AtomicUsize; N],
}
impl<const N: usize> HandlerTable<N> {
pub const fn new() -> Self {
Self {
handlers: [const { AtomicUsize::new(0) }; N],
}
}
pub fn register_handler(&self, idx: usize, handler: Handler) -> bool {
if idx >= N {
return false;
}
self.handlers[idx]
.compare_exchange(0, handler as usize, Ordering::Acquire, Ordering::Relaxed)
.is_ok()
}
pub fn unregister_handler(&self, idx: usize) -> Option<Handler> {
if idx >= N {
return None;
}
let handler = self.handlers[idx].swap(0, Ordering::Acquire);
if handler != 0 {
Some(unsafe { core::mem::transmute::<usize, fn()>(handler) })
} else {
None
}
}
pub fn handle(&self, idx: usize) -> bool {
if idx >= N {
return false;
}
let handler = self.handlers[idx].load(Ordering::Acquire);
if handler != 0 {
let handler: Handler = unsafe { core::mem::transmute(handler) };
handler();
true
} else {
false
}
}
}
impl<const N: usize> Default for HandlerTable<N> {
fn default() -> Self {
Self::new()
}
}