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