async_task_ffi/
lib.rs

1//! Task abstraction for building executors.
2//!
3//! **This is a fork of [async-task](https://docs.rs/async-task) with
4//! additional features useful for ffi based executors.**
5//!
6//! To spawn a future onto an executor, we first need to allocate it on the
7//! heap and keep some state attached to it. The state indicates whether the
8//! future is ready for polling, waiting to be woken up, or completed. Such a
9//! stateful future is called a *task*.
10//!
11//! All executors have a queue that holds scheduled tasks:
12//!
13//! ```
14//! let (sender, receiver) = flume::unbounded();
15//! #
16//! # // A future that will get spawned.
17//! # let future = async { 1 + 2 };
18//! #
19//! # // A function that schedules the task when it gets woken up.
20//! # let schedule = move |runnable| sender.send(runnable).unwrap();
21//! #
22//! # // Create a task.
23//! # let (runnable, task) = async_task_ffi::spawn(future, schedule);
24//! ```
25//!
26//! A task is created using either [`spawn()`], [`spawn_local()`],
27//! [`spawn_unchecked()`] or their `_with` variants which return a [`Runnable`]
28//! and a [`Task`]:
29//!
30//! ```
31//! # let (sender, receiver) = flume::unbounded();
32//! #
33//! // A future that will be spawned.
34//! let future = async { 1 + 2 };
35//!
36//! // A function that schedules the task when it gets woken up.
37//! let schedule = move |runnable| sender.send(runnable).unwrap();
38//!
39//! // Construct a task.
40//! let (runnable, task) = async_task_ffi::spawn(future, schedule);
41//!
42//! // Push the task into the queue by invoking its schedule function.
43//! runnable.schedule();
44//! ```
45//!
46//! The [`Runnable`] is used to poll the task's future, and the [`Task`] is
47//! used to await its output.
48//!
49//! Finally, we need a loop that takes scheduled tasks from the queue and runs
50//! them:
51//!
52//! ```no_run
53//! # let (sender, receiver) = flume::unbounded();
54//! #
55//! # // A future that will get spawned.
56//! # let future = async { 1 + 2 };
57//! #
58//! # // A function that schedules the task when it gets woken up.
59//! # let schedule = move |runnable| sender.send(runnable).unwrap();
60//! #
61//! # // Create a task.
62//! # let (runnable, task) = async_task_ffi::spawn(future, schedule);
63//! #
64//! # // Push the task into the queue by invoking its schedule function.
65//! # runnable.schedule();
66//! #
67//! for runnable in receiver {
68//!     runnable.run();
69//! }
70//! ```
71//!
72//! Method [`run()`][`Runnable::run()`] polls the task's future once. Then, the
73//! [`Runnable`] vanishes and only reappears when its
74//! [`Waker`][`core::task::Waker`] wakes the task, thus scheduling it to be run
75//! again.
76
77#![cfg_attr(not(feature = "std"), no_std)]
78#![warn(missing_docs, missing_debug_implementations, rust_2018_idioms)]
79#![doc(test(attr(deny(rust_2018_idioms, warnings))))]
80#![doc(test(attr(allow(unused_extern_crates, unused_variables))))]
81
82extern crate alloc;
83
84mod header;
85mod raw;
86mod runnable;
87mod state;
88mod task;
89mod utils;
90
91pub use crate::runnable::{spawn, spawn_unchecked, spawn_unchecked_with, spawn_with, Runnable};
92pub use crate::task::Task;
93
94#[cfg(feature = "std")]
95pub use crate::runnable::{spawn_local, spawn_local_with};