use core::ptr::NonNull;
use esp_hal::time::Instant;
use crate::{
SCHEDULER,
task::{TaskList, TaskPtr, TaskReadyQueueElement},
};
pub(crate) struct WaitQueue {
pub(crate) waiting_tasks: TaskList<TaskReadyQueueElement>,
}
impl WaitQueue {
pub(crate) const fn new() -> Self {
Self {
waiting_tasks: TaskList::new(),
}
}
pub(crate) fn notify(&mut self) {
SCHEDULER.with(|scheduler| {
while let Some(waken_task) = self.waiting_tasks.pop() {
scheduler.resume_task(waken_task);
}
});
}
pub(crate) fn wait_with_deadline(&mut self, deadline: Instant) {
SCHEDULER.with(|scheduler| {
let mut task = SCHEDULER.current_task();
if scheduler.sleep_task_until(task, deadline) {
self.waiting_tasks.push(task);
unsafe {
task.as_mut().current_wait_queue = Some(NonNull::from(self));
}
crate::task::yield_task();
}
});
}
pub(crate) fn remove(&mut self, task: TaskPtr) {
self.waiting_tasks.remove(task);
}
}
impl Drop for WaitQueue {
fn drop(&mut self) {
debug_assert!(
self.waiting_tasks.is_empty(),
"WaitQueue dropped while tasks are still waiting"
);
}
}