1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
//! # Erased Task
//! Hides a `Task`'s output type, so tasks of every output
//! type can share one table
use crate::futures::task::{
Task,
sealed::{Park, Step},
};
use crate::modules::input::token;
/// A `Task` with its output type erased
pub(crate) trait ErasedTask: Send {
/// Runs one step of the task, writing its output into
/// `payload` if the run finished
///
/// `resumed` is a run coming back from a park, which carries
/// on where it was rather than preparing afresh
///
/// ## Returns
/// What the task is waiting on, if it parked. Nothing is
/// written in that case
///
/// ## Safety
/// `payload` must point at enough writable, aligned bytes for
/// the output, and anything already there must have been
/// dropped
unsafe fn run(
&mut self,
reactor_id: i32,
task_id: usize,
payload: *mut u8,
resumed: bool,
) -> Option<Park>;
}
impl<F> ErasedTask for F
where
F: Task,
{
#[inline(always)]
unsafe fn run(
&mut self,
reactor_id: i32,
task_id: usize,
payload: *mut u8,
resumed: bool,
) -> Option<Park> {
// Spawned tasks prepare here, on the thread about to run them
if !resumed {
self.prepare(token());
}
match self.step(token(), reactor_id, task_id) {
Step::Done(out) => {
unsafe { payload.cast::<F::Output>().write(out) };
None
}
Step::Park(park) => Some(park),
}
}
}