use crate::runtime::task::{Cell, Harness, Header, Schedule, State}; use std::future::Future; use std::ptr::NonNull; use std::task::{Poll, Waker}; /// Raw task handle pub(super) struct RawTask { ptr: NonNull
, } pub(super) struct Vtable { /// Poll the future pub(super) poll: unsafe fn(NonNull
), /// Deallocate the memory pub(super) dealloc: unsafe fn(NonNull
), /// Read the task output, if complete pub(super) try_read_output: unsafe fn(NonNull
, *mut (), &Waker), /// The join handle has been dropped pub(super) drop_join_handle_slow: unsafe fn(NonNull
), /// Scheduler is being shutdown pub(super) shutdown: unsafe fn(NonNull
), } /// Get the vtable for the requested `T` and `S` generics. pub(super) fn vtable() -> &'static Vtable { &Vtable { poll: poll::, dealloc: dealloc::, try_read_output: try_read_output::, drop_join_handle_slow: drop_join_handle_slow::, shutdown: shutdown::, } } impl RawTask { pub(super) fn new(task: T) -> RawTask where T: Future, S: Schedule, { let ptr = Box::into_raw(Cell::<_, S>::new(task, State::new())); let ptr = unsafe { NonNull::new_unchecked(ptr as *mut Header) }; RawTask { ptr } } pub(super) unsafe fn from_raw(ptr: NonNull
) -> RawTask { RawTask { ptr } } /// Returns a reference to the task's meta structure. /// /// Safe as `Header` is `Sync`. pub(super) fn header(&self) -> &Header { unsafe { self.ptr.as_ref() } } /// Safety: mutual exclusion is required to call this function. pub(super) fn poll(self) { let vtable = self.header().vtable; unsafe { (vtable.poll)(self.ptr) } } pub(super) fn dealloc(self) { let vtable = self.header().vtable; unsafe { (vtable.dealloc)(self.ptr); } } /// Safety: `dst` must be a `*mut Poll>` where `T` /// is the future stored by the task. pub(super) unsafe fn try_read_output(self, dst: *mut (), waker: &Waker) { let vtable = self.header().vtable; (vtable.try_read_output)(self.ptr, dst, waker); } pub(super) fn drop_join_handle_slow(self) { let vtable = self.header().vtable; unsafe { (vtable.drop_join_handle_slow)(self.ptr) } } pub(super) fn shutdown(self) { let vtable = self.header().vtable; unsafe { (vtable.shutdown)(self.ptr) } } } impl Clone for RawTask { fn clone(&self) -> Self { RawTask { ptr: self.ptr } } } impl Copy for RawTask {} unsafe fn poll(ptr: NonNull
) { let harness = Harness::::from_raw(ptr); harness.poll(); } unsafe fn dealloc(ptr: NonNull
) { let harness = Harness::::from_raw(ptr); harness.dealloc(); } unsafe fn try_read_output( ptr: NonNull
, dst: *mut (), waker: &Waker, ) { let out = &mut *(dst as *mut Poll>); let harness = Harness::::from_raw(ptr); harness.try_read_output(out, waker); } unsafe fn drop_join_handle_slow(ptr: NonNull
) { let harness = Harness::::from_raw(ptr); harness.drop_join_handle_slow() } unsafe fn shutdown(ptr: NonNull
) { let harness = Harness::::from_raw(ptr); harness.shutdown() }