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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
//! Task abstraction for building executors.
//!
//! **This is a fork of [async-task](https://docs.rs/async-task) with
//! additional features useful for ffi based executors.**
//!
//! To spawn a future onto an executor, we first need to allocate it on the
//! heap and keep some state attached to it. The state indicates whether the
//! future is ready for polling, waiting to be woken up, or completed. Such a
//! stateful future is called a *task*.
//!
//! All executors have a queue that holds scheduled tasks:
//!
//! ```
//! let (sender, receiver) = flume::unbounded();
//! #
//! # // A future that will get spawned.
//! # let future = async { 1 + 2 };
//! #
//! # // A function that schedules the task when it gets woken up.
//! # let schedule = move |runnable| sender.send(runnable).unwrap();
//! #
//! # // Create a task.
//! # let (runnable, task) = async_task_ffi::spawn(future, schedule);
//! ```
//!
//! A task is created using either [`spawn()`], [`spawn_local()`],
//! [`spawn_unchecked()`] or their `_with` variants which return a [`Runnable`]
//! and a [`Task`]:
//!
//! ```
//! # let (sender, receiver) = flume::unbounded();
//! #
//! // A future that will be spawned.
//! let future = async { 1 + 2 };
//!
//! // A function that schedules the task when it gets woken up.
//! let schedule = move |runnable| sender.send(runnable).unwrap();
//!
//! // Construct a task.
//! let (runnable, task) = async_task_ffi::spawn(future, schedule);
//!
//! // Push the task into the queue by invoking its schedule function.
//! runnable.schedule();
//! ```
//!
//! The [`Runnable`] is used to poll the task's future, and the [`Task`] is
//! used to await its output.
//!
//! Finally, we need a loop that takes scheduled tasks from the queue and runs
//! them:
//!
//! ```no_run
//! # let (sender, receiver) = flume::unbounded();
//! #
//! # // A future that will get spawned.
//! # let future = async { 1 + 2 };
//! #
//! # // A function that schedules the task when it gets woken up.
//! # let schedule = move |runnable| sender.send(runnable).unwrap();
//! #
//! # // Create a task.
//! # let (runnable, task) = async_task_ffi::spawn(future, schedule);
//! #
//! # // Push the task into the queue by invoking its schedule function.
//! # runnable.schedule();
//! #
//! for runnable in receiver {
//! runnable.run();
//! }
//! ```
//!
//! Method [`run()`][`Runnable::run()`] polls the task's future once. Then, the
//! [`Runnable`] vanishes and only reappears when its
//! [`Waker`][`core::task::Waker`] wakes the task, thus scheduling it to be run
//! again.
extern crate alloc;
pub use crate;
pub use crateTask;
pub use crate;