use crate::executor::ExecutorHandle;
use crate::task::Task;
use std::sync::Arc;
use std::task::{RawWaker, RawWakerVTable, Waker};
use std::thread::Thread;
pub struct WakerData {
task: Arc<Task>,
handle: Arc<ExecutorHandle>,
}
pub fn task_waker(task: Arc<Task>, handle: Arc<ExecutorHandle>) -> Waker {
let data = Box::new(WakerData { task, handle });
let ptr = Box::into_raw(data) as *const ();
unsafe { Waker::from_raw(RawWaker::new(ptr, &VTABLE)) }
}
unsafe fn clone(data: *const ()) -> RawWaker {
let data = unsafe { &*(data as *const WakerData) };
let cloned = Box::new(WakerData {
task: data.task.clone(),
handle: data.handle.clone(),
});
RawWaker::new(Box::into_raw(cloned) as *const (), &VTABLE)
}
unsafe fn wake(data: *const ()) {
let data = unsafe { Box::from_raw(data as *mut WakerData) };
data.handle.enqueue(data.task);
}
unsafe fn wake_by_ref(data: *const ()) {
let data = unsafe { &*(data as *const WakerData) };
data.handle.enqueue(data.task.clone());
}
unsafe fn drop(data: *const ()) {
let _ = unsafe { Box::from_raw(data as *mut WakerData) };
}
static VTABLE: RawWakerVTable = RawWakerVTable::new(clone, wake, wake_by_ref, drop);
pub fn unpark_waker(thread: Thread) -> Waker {
let ptr = Box::into_raw(Box::new(thread)) as *const ();
unsafe { Waker::from_raw(RawWaker::new(ptr, &UNPARK_VTABLE)) }
}
unsafe fn clone_unpark(ptr: *const ()) -> RawWaker {
let thread = unsafe { (*(ptr as *const Thread)).clone() };
RawWaker::new(Box::into_raw(Box::new(thread)) as *const (), &UNPARK_VTABLE)
}
unsafe fn wake_unpark(ptr: *const ()) {
let thread = unsafe { *Box::from_raw(ptr as *mut Thread) };
thread.unpark();
}
unsafe fn wake_unpark_by_ref(ptr: *const ()) {
let thread = unsafe { &*(ptr as *const Thread) };
thread.unpark();
}
unsafe fn drop_unpark(ptr: *const ()) {
let _ = unsafe { Box::from_raw(ptr as *mut Thread) };
}
static UNPARK_VTABLE: RawWakerVTable =
RawWakerVTable::new(clone_unpark, wake_unpark, wake_unpark_by_ref, drop_unpark);