use once_cell::unsync::Lazy;
use std::cell::{Cell, RefCell};
use std::collections::VecDeque;
use std::rc::Rc;
struct QueueState {
tasks: RefCell<VecDeque<Rc<super::task::Task>>>,
is_spinning: Cell<bool>,
}
impl QueueState {
fn run_all(&self) {
debug_assert!(self.is_spinning.get());
while let Some(task) = self.tasks.borrow_mut().pop_front() {
task.run();
}
self.is_spinning.set(false);
}
}
struct Queue {
state: Rc<QueueState>,
}
impl Queue {
fn push_task(&self, task: Rc<super::task::Task>) {
self.state.tasks.borrow_mut().push_back(task);
if !self.state.is_spinning.replace(true) {
self.state.run_all();
}
}
}
impl Queue {
fn new() -> Self {
let state = Rc::new(QueueState {
is_spinning: Cell::new(false),
tasks: RefCell::new(VecDeque::new()),
});
Self { state }
}
}
static mut QUEUE: Lazy<Queue> = Lazy::new(Queue::new);
pub(crate) fn push_task(task: Rc<super::task::Task>) {
unsafe { QUEUE.push_task(task) }
}