use super::{worker_from, RawTask};
use crate::event::Scheduler;
use core::ptr::NonNull;
use core::task::{RawWaker, RawWakerVTable, Waker};
impl RawTask {
pub(crate) fn task_waker(&self) -> Waker {
let raw_waker = RawWaker::new((self as *const Self).cast::<()>(), &TASKWAKER_VTABLE);
unsafe { Waker::from_raw(raw_waker) }
}
}
const RAWWAKER_VTABLE: RawWakerVTable =
RawWakerVTable::new(waker_clone, waker_wake, waker_wake_by_ref, waker_drop);
unsafe fn waker_clone(this: *const ()) -> RawWaker {
let task = unsafe { &*this.cast::<RawTask>() };
task.inc_ref();
RawWaker::new(this, &RAWWAKER_VTABLE)
}
unsafe fn waker_wake(this: *const ()) {
let task = unsafe { &*this.cast::<RawTask>() };
task.wake();
task.dec_ref();
}
unsafe fn waker_wake_by_ref(this: *const ()) {
let task = unsafe { &*this.cast::<RawTask>() };
task.wake();
}
unsafe fn waker_drop(this: *const ()) {
let task = unsafe { &*this.cast::<RawTask>() };
task.dec_ref();
}
const TASKWAKER_VTABLE: RawWakerVTable =
RawWakerVTable::new(waker_clone, waker_wake_by_ref, waker_wake_by_ref, task_waker_drop);
unsafe fn task_waker_drop(_this: *const ()) {}
pub(crate) struct TaskWaker<'a> {
pub(crate) waker: Waker,
pub(crate) task: NonNull<RawTask>,
pub(crate) sched: &'a mut Scheduler,
}
impl<'a> TaskWaker<'a> {
pub(crate) fn new(task: &mut RawTask, sched: &'a mut Scheduler) -> Self {
let worker = unsafe { worker_from(sched) };
worker.set_current_task(Some(NonNull::from(&*task)));
Self {
waker: task.task_waker(),
task: NonNull::from(task),
sched,
}
}
}
impl Drop for TaskWaker<'_> {
fn drop(&mut self) {
let worker = unsafe { worker_from(self.sched) };
worker.set_current_task(None);
}
}