use std::collections::VecDeque;
use std::task::{RawWaker, RawWakerVTable, Waker};
use dambi::LocalCell;
use crate::SlotId;
const _: () = assert!(std::mem::size_of::<SlotId>() == std::mem::size_of::<*const ()>());
thread_local! {
static READY_QUEUE: LocalCell<VecDeque<SlotId>> =
const { LocalCell::new(VecDeque::new()) };
}
pub(crate) struct WakeQueue;
impl WakeQueue {
#[inline]
pub(crate) fn push(id: SlotId) {
READY_QUEUE.with(|q| q.get_mut().push_back(id));
}
#[inline]
pub(crate) fn next() -> Option<SlotId> {
READY_QUEUE.with(|q| q.get_mut().pop_front())
}
#[inline]
pub(crate) fn is_pending() -> bool {
READY_QUEUE.with(|q| !q.get().is_empty())
}
#[inline]
pub(crate) fn reserve(cap: usize) {
READY_QUEUE.with(|q| q.get_mut().reserve(cap));
}
pub(crate) fn make_waker(id: SlotId) -> Waker {
let data: *const () = unsafe { std::mem::transmute(id) };
let raw = RawWaker::new(data, &Self::VTABLE);
unsafe { Waker::from_raw(raw) }
}
const VTABLE: RawWakerVTable = RawWakerVTable::new(
Self::vt_clone,
Self::vt_wake,
Self::vt_wake_by_ref,
Self::vt_drop,
);
unsafe fn vt_clone(data: *const ()) -> RawWaker {
RawWaker::new(data, &Self::VTABLE)
}
unsafe fn vt_wake(data: *const ()) {
let id: SlotId = unsafe { std::mem::transmute(data) };
Self::push(id);
}
unsafe fn vt_wake_by_ref(data: *const ()) {
let id: SlotId = unsafe { std::mem::transmute(data) };
Self::push(id);
}
unsafe fn vt_drop(_data: *const ()) {}
}