• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use crate::future::Future;
2 use crate::runtime::task::{Cell, Harness, Header, Schedule, State};
3 
4 use std::ptr::NonNull;
5 use std::task::{Poll, Waker};
6 
7 /// Raw task handle
8 pub(super) struct RawTask {
9     ptr: NonNull<Header>,
10 }
11 
12 pub(super) struct Vtable {
13     /// Polls the future.
14     pub(super) poll: unsafe fn(NonNull<Header>),
15 
16     /// Deallocates the memory.
17     pub(super) dealloc: unsafe fn(NonNull<Header>),
18 
19     /// Reads the task output, if complete.
20     pub(super) try_read_output: unsafe fn(NonNull<Header>, *mut (), &Waker),
21 
22     /// The join handle has been dropped.
23     pub(super) drop_join_handle_slow: unsafe fn(NonNull<Header>),
24 
25     /// The task is remotely aborted.
26     pub(super) remote_abort: unsafe fn(NonNull<Header>),
27 
28     /// Scheduler is being shutdown.
29     pub(super) shutdown: unsafe fn(NonNull<Header>),
30 }
31 
32 /// Get the vtable for the requested `T` and `S` generics.
vtable<T: Future, S: Schedule>() -> &'static Vtable33 pub(super) fn vtable<T: Future, S: Schedule>() -> &'static Vtable {
34     &Vtable {
35         poll: poll::<T, S>,
36         dealloc: dealloc::<T, S>,
37         try_read_output: try_read_output::<T, S>,
38         drop_join_handle_slow: drop_join_handle_slow::<T, S>,
39         remote_abort: remote_abort::<T, S>,
40         shutdown: shutdown::<T, S>,
41     }
42 }
43 
44 impl RawTask {
new<T, S>(task: T, scheduler: S) -> RawTask where T: Future, S: Schedule,45     pub(super) fn new<T, S>(task: T, scheduler: S) -> RawTask
46     where
47         T: Future,
48         S: Schedule,
49     {
50         let ptr = Box::into_raw(Cell::<_, S>::new(task, scheduler, State::new()));
51         let ptr = unsafe { NonNull::new_unchecked(ptr as *mut Header) };
52 
53         RawTask { ptr }
54     }
55 
from_raw(ptr: NonNull<Header>) -> RawTask56     pub(super) unsafe fn from_raw(ptr: NonNull<Header>) -> RawTask {
57         RawTask { ptr }
58     }
59 
60     /// Returns a reference to the task's meta structure.
61     ///
62     /// Safe as `Header` is `Sync`.
header(&self) -> &Header63     pub(super) fn header(&self) -> &Header {
64         unsafe { self.ptr.as_ref() }
65     }
66 
67     /// Safety: mutual exclusion is required to call this function.
poll(self)68     pub(super) fn poll(self) {
69         let vtable = self.header().vtable;
70         unsafe { (vtable.poll)(self.ptr) }
71     }
72 
dealloc(self)73     pub(super) fn dealloc(self) {
74         let vtable = self.header().vtable;
75         unsafe {
76             (vtable.dealloc)(self.ptr);
77         }
78     }
79 
80     /// Safety: `dst` must be a `*mut Poll<super::Result<T::Output>>` where `T`
81     /// is the future stored by the task.
try_read_output(self, dst: *mut (), waker: &Waker)82     pub(super) unsafe fn try_read_output(self, dst: *mut (), waker: &Waker) {
83         let vtable = self.header().vtable;
84         (vtable.try_read_output)(self.ptr, dst, waker);
85     }
86 
drop_join_handle_slow(self)87     pub(super) fn drop_join_handle_slow(self) {
88         let vtable = self.header().vtable;
89         unsafe { (vtable.drop_join_handle_slow)(self.ptr) }
90     }
91 
shutdown(self)92     pub(super) fn shutdown(self) {
93         let vtable = self.header().vtable;
94         unsafe { (vtable.shutdown)(self.ptr) }
95     }
96 
remote_abort(self)97     pub(super) fn remote_abort(self) {
98         let vtable = self.header().vtable;
99         unsafe { (vtable.remote_abort)(self.ptr) }
100     }
101 }
102 
103 impl Clone for RawTask {
clone(&self) -> Self104     fn clone(&self) -> Self {
105         RawTask { ptr: self.ptr }
106     }
107 }
108 
109 impl Copy for RawTask {}
110 
poll<T: Future, S: Schedule>(ptr: NonNull<Header>)111 unsafe fn poll<T: Future, S: Schedule>(ptr: NonNull<Header>) {
112     let harness = Harness::<T, S>::from_raw(ptr);
113     harness.poll();
114 }
115 
dealloc<T: Future, S: Schedule>(ptr: NonNull<Header>)116 unsafe fn dealloc<T: Future, S: Schedule>(ptr: NonNull<Header>) {
117     let harness = Harness::<T, S>::from_raw(ptr);
118     harness.dealloc();
119 }
120 
try_read_output<T: Future, S: Schedule>( ptr: NonNull<Header>, dst: *mut (), waker: &Waker, )121 unsafe fn try_read_output<T: Future, S: Schedule>(
122     ptr: NonNull<Header>,
123     dst: *mut (),
124     waker: &Waker,
125 ) {
126     let out = &mut *(dst as *mut Poll<super::Result<T::Output>>);
127 
128     let harness = Harness::<T, S>::from_raw(ptr);
129     harness.try_read_output(out, waker);
130 }
131 
drop_join_handle_slow<T: Future, S: Schedule>(ptr: NonNull<Header>)132 unsafe fn drop_join_handle_slow<T: Future, S: Schedule>(ptr: NonNull<Header>) {
133     let harness = Harness::<T, S>::from_raw(ptr);
134     harness.drop_join_handle_slow()
135 }
136 
remote_abort<T: Future, S: Schedule>(ptr: NonNull<Header>)137 unsafe fn remote_abort<T: Future, S: Schedule>(ptr: NonNull<Header>) {
138     let harness = Harness::<T, S>::from_raw(ptr);
139     harness.remote_abort()
140 }
141 
shutdown<T: Future, S: Schedule>(ptr: NonNull<Header>)142 unsafe fn shutdown<T: Future, S: Schedule>(ptr: NonNull<Header>) {
143     let harness = Harness::<T, S>::from_raw(ptr);
144     harness.shutdown()
145 }
146