use core::cell::RefCell;
use alloc::collections::vec_deque::VecDeque;
use async_task::Runnable;
use embassy_sync::blocking_mutex::{
raw::{CriticalSectionRawMutex, RawMutex},
Mutex,
};
extern crate alloc;
pub trait ExecutorQueue: Sized {
fn new() -> Self;
fn push(&self, runnable: Runnable);
fn pop(&self) -> Option<Runnable>;
}
pub struct UnboundQueue<M: RawMutex = CriticalSectionRawMutex>(
Mutex<M, RefCell<VecDeque<Runnable>>>,
);
impl<M: RawMutex> Default for UnboundQueue<M> {
fn default() -> Self {
Self::new()
}
}
impl<M: RawMutex> UnboundQueue<M> {
pub const fn new() -> Self {
Self(Mutex::new(RefCell::new(VecDeque::new())))
}
pub fn with_capacity(capacity: usize) -> Self {
Self(Mutex::new(RefCell::new(VecDeque::with_capacity(capacity))))
}
}
impl<M: RawMutex> ExecutorQueue for UnboundQueue<M>
where
M: RawMutex,
{
fn new() -> Self {
Self::new()
}
fn push(&self, runnable: Runnable) {
self.0.lock(|rc| {
let mut queue = rc.borrow_mut();
queue.push_back(runnable);
})
}
fn pop(&self) -> Option<Runnable> {
self.0.lock(|rc| {
let mut queue = rc.borrow_mut();
queue.pop_front()
})
}
}
pub struct BoundQueue<const C: usize = 64, M: RawMutex = CriticalSectionRawMutex>(
Mutex<M, RefCell<heapless::Deque<Runnable, C>>>,
);
impl<const C: usize, M: RawMutex> Default for BoundQueue<C, M> {
fn default() -> Self {
Self::new()
}
}
impl<const C: usize, M: RawMutex> BoundQueue<C, M> {
pub const fn new() -> Self {
Self(Mutex::new(RefCell::new(heapless::Deque::new())))
}
}
impl<const C: usize, M: RawMutex> ExecutorQueue for BoundQueue<C, M> {
fn new() -> Self {
Self::new()
}
fn push(&self, runnable: Runnable) {
self.0.lock(|rc| {
let mut queue = rc.borrow_mut();
queue
.push_back(runnable)
.expect("BoundQueue capacity exceeded");
})
}
fn pop(&self) -> Option<Runnable> {
self.0.lock(|rc| {
let mut queue = rc.borrow_mut();
queue.pop_front()
})
}
}