diff options
| author | ihciah <[email protected]> | 2021-12-02 14:38:25 +0800 |
|---|---|---|
| committer | ihciah <[email protected]> | 2021-12-02 14:38:25 +0800 |
| commit | 9df6a26f2f51aba824ceeee21179fbff4dd42d49 (patch) | |
| tree | 031cacffb874f003a313d5fe6094751927efcdf0 /monoio/src/task/raw.rs | |
Init: open-source
Diffstat (limited to 'monoio/src/task/raw.rs')
| -rw-r--r-- | monoio/src/task/raw.rs | 127 |
1 files changed, 127 insertions, 0 deletions
diff --git a/monoio/src/task/raw.rs b/monoio/src/task/raw.rs new file mode 100644 index 0000000..1df0137 --- /dev/null +++ b/monoio/src/task/raw.rs @@ -0,0 +1,127 @@ +use crate::task::{Cell, Harness, Header, Schedule}; + +use std::{ + future::Future, + ptr::NonNull, + task::{Poll, Waker}, +}; + +pub(crate) struct RawTask { + ptr: NonNull<Header>, +} + +impl Clone for RawTask { + fn clone(&self) -> Self { + RawTask { ptr: self.ptr } + } +} + +impl Copy for RawTask {} + +pub(crate) struct Vtable { + /// Poll the future + pub(crate) poll: unsafe fn(NonNull<Header>), + /// Deallocate the memory + pub(crate) dealloc: unsafe fn(NonNull<Header>), + + /// Read the task output, if complete + pub(crate) try_read_output: unsafe fn(NonNull<Header>, *mut (), &Waker), + + /// The join handle has been dropped + pub(crate) drop_join_handle_slow: unsafe fn(NonNull<Header>), +} + +/// Get the vtable for the requested `T` and `S` generics. +pub(super) fn vtable<T: Future, S: Schedule>() -> &'static Vtable { + &Vtable { + poll: poll::<T, S>, + dealloc: dealloc::<T, S>, + try_read_output: try_read_output::<T, S>, + drop_join_handle_slow: drop_join_handle_slow::<T, S>, + } +} + +impl RawTask { + #[cfg(not(feature = "sync"))] + pub(crate) fn new<T, S>(task: T, scheduler: S) -> RawTask + where + T: Future, + S: Schedule, + { + let ptr = Box::into_raw(Cell::new(task, scheduler)); + let ptr = unsafe { NonNull::new_unchecked(ptr as *mut Header) }; + + RawTask { ptr } + } + + #[cfg(feature = "sync")] + pub(crate) fn new<T, S>(owner_id: usize, task: T, scheduler: S) -> RawTask + where + T: Future, + S: Schedule, + { + let ptr = Box::into_raw(Cell::new(owner_id, task, scheduler)); + let ptr = unsafe { NonNull::new_unchecked(ptr as *mut Header) }; + + RawTask { ptr } + } + + pub(crate) unsafe fn from_raw(ptr: NonNull<Header>) -> RawTask { + RawTask { ptr } + } + + pub(crate) fn header(&self) -> &Header { + unsafe { self.ptr.as_ref() } + } + + /// Safety: mutual exclusion is required to call this function. + pub(crate) fn poll(self) { + let vtable = self.header().vtable; + unsafe { (vtable.poll)(self.ptr) } + } + + pub(crate) fn dealloc(self) { + let vtable = self.header().vtable; + unsafe { + (vtable.dealloc)(self.ptr); + } + } + + /// Safety: `dst` must be a `*mut Poll<super::Result<T::Output>>` where `T` + /// is the future stored by the task. + pub(crate) unsafe fn try_read_output(self, dst: *mut (), waker: &Waker) { + let vtable = self.header().vtable; + (vtable.try_read_output)(self.ptr, dst, waker); + } + + pub(crate) fn drop_join_handle_slow(self) { + let vtable = self.header().vtable; + unsafe { (vtable.drop_join_handle_slow)(self.ptr) } + } +} + +unsafe fn poll<T: Future, S: Schedule>(ptr: NonNull<Header>) { + let harness = Harness::<T, S>::from_raw(ptr); + harness.poll(); +} + +unsafe fn dealloc<T: Future, S: Schedule>(ptr: NonNull<Header>) { + let harness = Harness::<T, S>::from_raw(ptr); + harness.dealloc(); +} + +unsafe fn try_read_output<T: Future, S: Schedule>( + ptr: NonNull<Header>, + dst: *mut (), + waker: &Waker, +) { + let out = &mut *(dst as *mut Poll<T::Output>); + + let harness = Harness::<T, S>::from_raw(ptr); + harness.try_read_output(out, waker); +} + +unsafe fn drop_join_handle_slow<T: Future, S: Schedule>(ptr: NonNull<Header>) { + let harness = Harness::<T, S>::from_raw(ptr); + harness.drop_join_handle_slow() +} |
