use core::ptr;
use core::ptr::NonNull;
use atomic_polyfill::{AtomicPtr, Ordering};
use critical_section::CriticalSection;
use super::TaskHeader;
pub(crate) struct RunQueueItem {
next: AtomicPtr<TaskHeader>,
}
impl RunQueueItem {
pub const fn new() -> Self {
Self {
next: AtomicPtr::new(ptr::null_mut()),
}
}
}
pub(crate) struct RunQueue {
head: AtomicPtr<TaskHeader>,
}
impl RunQueue {
pub const fn new() -> Self {
Self {
head: AtomicPtr::new(ptr::null_mut()),
}
}
#[inline(always)]
pub(crate) unsafe fn enqueue(&self, _cs: CriticalSection, task: NonNull<TaskHeader>) -> bool {
let prev = self.head.load(Ordering::Relaxed);
task.as_ref().run_queue_item.next.store(prev, Ordering::Relaxed);
self.head.store(task.as_ptr(), Ordering::Relaxed);
prev.is_null()
}
pub(crate) fn dequeue_all(&self, on_task: impl Fn(NonNull<TaskHeader>)) {
let mut ptr = self.head.swap(ptr::null_mut(), Ordering::AcqRel);
while let Some(task) = NonNull::new(ptr) {
let next = unsafe { task.as_ref() }.run_queue_item.next.load(Ordering::Relaxed);
on_task(task);
ptr = next
}
}
}