use core::{
mem::ManuallyDrop,
ptr,
task::{RawWaker, RawWakerVTable, Waker},
};
use super::coroutine::{
CoroutineHeader, release_reference, retain_reference, schedule, schedule_sync,
};
static VTABLE: RawWakerVTable = RawWakerVTable::new(clone_waker, wake, wake_by_ref, drop_waker);
pub(super) unsafe fn coroutine_waker(header: *mut CoroutineHeader) -> Waker {
let header_ref = unsafe {
&*header
};
retain_reference(header_ref);
let raw = RawWaker::new(header.cast(), &VTABLE);
unsafe {
Waker::from_raw(raw)
}
}
pub(super) fn wake_sync(waker: Waker) {
if !ptr::eq(waker.vtable(), &VTABLE) {
waker.wake();
return;
}
let header = waker.data().cast_mut().cast::<CoroutineHeader>();
let _waker = ManuallyDrop::new(waker);
unsafe {
schedule_sync(header);
release_reference(header);
}
}
unsafe fn clone_waker(data: *const ()) -> RawWaker {
let header = data.cast_mut().cast::<CoroutineHeader>();
let header_ref = unsafe {
&*header
};
retain_reference(header_ref);
RawWaker::new(data, &VTABLE)
}
unsafe fn wake(data: *const ()) {
let header = data.cast_mut().cast::<CoroutineHeader>();
unsafe {
schedule(header);
release_reference(header);
}
}
unsafe fn wake_by_ref(data: *const ()) {
let header = data.cast_mut().cast::<CoroutineHeader>();
unsafe {
schedule(header);
}
}
unsafe fn drop_waker(data: *const ()) {
let header = data.cast_mut().cast::<CoroutineHeader>();
unsafe {
release_reference(header);
}
}