tokio/task/mod.rs
1//! Asynchronous green-threads.
2//!
3//! ## What are Tasks?
4//!
5//! A _task_ is a light weight, non-blocking unit of execution. A task is similar
6//! to an OS thread, but rather than being managed by the OS scheduler, they are
7//! managed by the [Tokio runtime][rt]. Another name for this general pattern is
8//! [green threads]. If you are familiar with [Go's goroutines], [Kotlin's
9//! coroutines], or [Erlang's processes], you can think of Tokio's tasks as
10//! something similar.
11//!
12//! Key points about tasks include:
13//!
14//! * Tasks are **light weight**. Because tasks are scheduled by the Tokio
15//! runtime rather than the operating system, creating new tasks or switching
16//! between tasks does not require a context switch and has fairly low
17//! overhead. Creating, running, and destroying large numbers of tasks is
18//! quite cheap, especially compared to OS threads.
19//!
20//! * Tasks are scheduled **cooperatively**. Most operating systems implement
21//! _preemptive multitasking_. This is a scheduling technique where the
22//! operating system allows each thread to run for a period of time, and then
23//! _preempts_ it, temporarily pausing that thread and switching to another.
24//! Tasks, on the other hand, implement _cooperative multitasking_. In
25//! cooperative multitasking, a task is allowed to run until it _yields_,
26//! indicating to the Tokio runtime's scheduler that it cannot currently
27//! continue executing. When a task yields, the Tokio runtime switches to
28//! executing the next task.
29//!
30//! * Tasks are **non-blocking**. Typically, when an OS thread performs I/O or
31//! must synchronize with another thread, it _blocks_, allowing the OS to
32//! schedule another thread. When a task cannot continue executing, it must
33//! yield instead, allowing the Tokio runtime to schedule another task. Tasks
34//! should generally not perform system calls or other operations that could
35//! block a thread, as this would prevent other tasks running on the same
36//! thread from executing as well. Instead, this module provides APIs for
37//! running blocking operations in an asynchronous context.
38//!
39//! [rt]: crate::runtime
40//! [green threads]: https://en.wikipedia.org/wiki/Green_threads
41//! [Go's goroutines]: https://tour.golang.org/concurrency/1
42//! [Kotlin's coroutines]: https://kotlinlang.org/docs/reference/coroutines-overview.html
43//! [Erlang's processes]: http://erlang.org/doc/getting_started/conc_prog.html#processes
44//!
45//! ## Working with Tasks
46//!
47//! This module provides the following APIs for working with tasks:
48//!
49//! ### Spawning
50//!
51//! Perhaps the most important function in this module is [`task::spawn`]. This
52//! function can be thought of as an async equivalent to the standard library's
53//! [`thread::spawn`][`std::thread::spawn`]. It takes an `async` block or other
54//! [future], and creates a new task to run that work concurrently:
55//!
56//! ```
57//! use tokio::task;
58//!
59//! # async fn doc() {
60//! task::spawn(async {
61//! // perform some work here...
62//! });
63//! # }
64//! ```
65//!
66//! Like [`std::thread::spawn`], `task::spawn` returns a [`JoinHandle`] struct.
67//! A `JoinHandle` is itself a future which may be used to await the output of
68//! the spawned task. For example:
69//!
70//! ```
71//! use tokio::task;
72//!
73//! # #[tokio::main] async fn main() -> Result<(), Box<dyn std::error::Error>> {
74//! let join = task::spawn(async {
75//! // ...
76//! "hello world!"
77//! });
78//!
79//! // ...
80//!
81//! // Await the result of the spawned task.
82//! let result = join.await?;
83//! assert_eq!(result, "hello world!");
84//! # Ok(())
85//! # }
86//! ```
87//!
88//! Again, like `std::thread`'s [`JoinHandle` type][thread_join], if the spawned
89//! task panics, awaiting its `JoinHandle` will return a [`JoinError`]. For
90//! example:
91//!
92//! ```
93//! use tokio::task;
94//!
95//! # #[tokio::main] async fn main() {
96//! let join = task::spawn(async {
97//! panic!("something bad happened!")
98//! });
99//!
100//! // The returned result indicates that the task failed.
101//! assert!(join.await.is_err());
102//! # }
103//! ```
104//!
105//! `spawn`, `JoinHandle`, and `JoinError` are present when the "rt"
106//! feature flag is enabled.
107//!
108//! [`task::spawn`]: crate::task::spawn()
109//! [future]: std::future::Future
110//! [`std::thread::spawn`]: std::thread::spawn
111//! [`JoinHandle`]: crate::task::JoinHandle
112//! [thread_join]: std::thread::JoinHandle
113//! [`JoinError`]: crate::task::JoinError
114//!
115//! #### Cancellation
116//!
117//! Spawned tasks may be cancelled using the [`JoinHandle::abort`] or
118//! [`AbortHandle::abort`] methods. When one of these methods are called, the
119//! task is signalled to shut down next time it yields at an `.await` point. If
120//! the task is already idle, then it will be shut down as soon as possible
121//! without running again before being shut down. Additionally, shutting down a
122//! Tokio runtime (e.g. by returning from `#[tokio::main]`) immediately cancels
123//! all tasks on it.
124//!
125//! When tasks are shut down, it will stop running at whichever `.await` it has
126//! yielded at. All local variables are destroyed by running their destructor.
127//! Once shutdown has completed, awaiting the [`JoinHandle`] will fail with a
128//! [cancelled error](crate::task::JoinError::is_cancelled).
129//!
130//! Note that aborting a task does not guarantee that it fails with a cancelled
131//! error, since it may complete normally first. For example, if the task does
132//! not yield to the runtime at any point between the call to `abort` and the
133//! end of the task, then the [`JoinHandle`] will instead report that the task
134//! exited normally.
135//!
136//! Be aware that tasks spawned using [`spawn_blocking`] cannot be aborted
137//! because they are not async. If you call `abort` on a `spawn_blocking`
138//! task, then this *will not have any effect*, and the task will continue
139//! running normally. The exception is if the task has not started running
140//! yet; in that case, calling `abort` may prevent the task from starting.
141//!
142//! Be aware that calls to [`JoinHandle::abort`] just schedule the task for
143//! cancellation, and will return before the cancellation has completed. To wait
144//! for cancellation to complete, wait for the task to finish by awaiting the
145//! [`JoinHandle`]. Similarly, the [`JoinHandle::is_finished`] method does not
146//! return `true` until the cancellation has finished.
147//!
148//! Calling [`JoinHandle::abort`] multiple times has the same effect as calling
149//! it once.
150//!
151//! Tokio also provides an [`AbortHandle`], which is like the [`JoinHandle`],
152//! except that it does not provide a mechanism to wait for the task to finish.
153//! Each task can only have one [`JoinHandle`], but it can have more than one
154//! [`AbortHandle`].
155//!
156//! [`JoinHandle::abort`]: crate::task::JoinHandle::abort
157//! [`AbortHandle::abort`]: crate::task::AbortHandle::abort
158//! [`AbortHandle`]: crate::task::AbortHandle
159//! [`JoinHandle::is_finished`]: crate::task::JoinHandle::is_finished
160//!
161//! ### Blocking and Yielding
162//!
163//! As we discussed above, code running in asynchronous tasks should not perform
164//! operations that can block. A blocking operation performed in a task running
165//! on a thread that is also running other tasks would block the entire thread,
166//! preventing other tasks from running.
167//!
168//! Instead, Tokio provides two APIs for running blocking operations in an
169//! asynchronous context: [`task::spawn_blocking`] and [`task::block_in_place`].
170//!
171//! Be aware that if you call a non-async method from async code, that non-async
172//! method is still inside the asynchronous context, so you should also avoid
173//! blocking operations there. This includes destructors of objects destroyed in
174//! async code.
175//!
176//! #### `spawn_blocking`
177//!
178//! The `task::spawn_blocking` function is similar to the `task::spawn` function
179//! discussed in the previous section, but rather than spawning an
180//! _non-blocking_ future on the Tokio runtime, it instead spawns a
181//! _blocking_ function on a dedicated thread pool for blocking tasks. For
182//! example:
183//!
184//! ```
185//! use tokio::task;
186//!
187//! # async fn docs() {
188//! task::spawn_blocking(|| {
189//! // do some compute-heavy work or call synchronous code
190//! });
191//! # }
192//! ```
193//!
194//! Just like `task::spawn`, `task::spawn_blocking` returns a `JoinHandle`
195//! which we can use to await the result of the blocking operation:
196//!
197//! ```rust
198//! # use tokio::task;
199//! # async fn docs() -> Result<(), Box<dyn std::error::Error>>{
200//! let join = task::spawn_blocking(|| {
201//! // do some compute-heavy work or call synchronous code
202//! "blocking completed"
203//! });
204//!
205//! let result = join.await?;
206//! assert_eq!(result, "blocking completed");
207//! # Ok(())
208//! # }
209//! ```
210//!
211//! #### `block_in_place`
212//!
213//! When using the [multi-threaded runtime][rt-multi-thread], the [`task::block_in_place`]
214//! function is also available. Like `task::spawn_blocking`, this function
215//! allows running a blocking operation from an asynchronous context. Unlike
216//! `spawn_blocking`, however, `block_in_place` works by transitioning the
217//! _current_ worker thread to a blocking thread, moving other tasks running on
218//! that thread to another worker thread. This can improve performance by avoiding
219//! context switches.
220//!
221//! For example:
222//!
223//! ```
224//! use tokio::task;
225//!
226//! # async fn docs() {
227//! let result = task::block_in_place(|| {
228//! // do some compute-heavy work or call synchronous code
229//! "blocking completed"
230//! });
231//!
232//! assert_eq!(result, "blocking completed");
233//! # }
234//! ```
235//!
236//! #### `yield_now`
237//!
238//! In addition, this module provides a [`task::yield_now`] async function
239//! that is analogous to the standard library's [`thread::yield_now`]. Calling
240//! and `await`ing this function will cause the current task to yield to the
241//! Tokio runtime's scheduler, allowing other tasks to be
242//! scheduled. Eventually, the yielding task will be polled again, allowing it
243//! to execute. For example:
244//!
245//! ```rust
246//! use tokio::task;
247//!
248//! # #[tokio::main] async fn main() {
249//! async {
250//! task::spawn(async {
251//! // ...
252//! println!("spawned task done!")
253//! });
254//!
255//! // Yield, allowing the newly-spawned task to execute first.
256//! task::yield_now().await;
257//! println!("main task done!");
258//! }
259//! # .await;
260//! # }
261//! ```
262//!
263//! ### Cooperative scheduling
264//!
265//! A single call to [`poll`] on a top-level task may potentially do a lot of
266//! work before it returns `Poll::Pending`. If a task runs for a long period of
267//! time without yielding back to the executor, it can starve other tasks
268//! waiting on that executor to execute them, or drive underlying resources.
269//! Since Rust does not have a runtime, it is difficult to forcibly preempt a
270//! long-running task. Instead, this module provides an opt-in mechanism for
271//! futures to collaborate with the executor to avoid starvation.
272//!
273//! Consider a future like this one:
274//!
275//! ```
276//! # use tokio_stream::{Stream, StreamExt};
277//! async fn drop_all<I: Stream + Unpin>(mut input: I) {
278//! while let Some(_) = input.next().await {}
279//! }
280//! ```
281//!
282//! It may look harmless, but consider what happens under heavy load if the
283//! input stream is _always_ ready. If we spawn `drop_all`, the task will never
284//! yield, and will starve other tasks and resources on the same executor.
285//!
286//! To account for this, Tokio has explicit yield points in a number of library
287//! functions, which force tasks to return to the executor periodically.
288//!
289//!
290//! #### unconstrained
291//!
292//! If necessary, [`task::unconstrained`] lets you opt a future out of Tokio's cooperative
293//! scheduling. When a future is wrapped with `unconstrained`, it will never be forced to yield to
294//! Tokio. For example:
295//!
296//! ```
297//! # #[tokio::main]
298//! # async fn main() {
299//! use tokio::{task, sync::mpsc};
300//!
301//! let fut = async {
302//! let (tx, mut rx) = mpsc::unbounded_channel();
303//!
304//! for i in 0..1000 {
305//! let _ = tx.send(());
306//! // This will always be ready. If coop was in effect, this code would be forced to yield
307//! // periodically. However, if left unconstrained, then this code will never yield.
308//! rx.recv().await;
309//! }
310//! };
311//!
312//! task::unconstrained(fut).await;
313//! # }
314//! ```
315//!
316//! [`task::spawn_blocking`]: crate::task::spawn_blocking
317//! [`task::block_in_place`]: crate::task::block_in_place
318//! [rt-multi-thread]: ../runtime/index.html#threaded-scheduler
319//! [`task::yield_now`]: crate::task::yield_now()
320//! [`thread::yield_now`]: std::thread::yield_now
321//! [`task::unconstrained`]: crate::task::unconstrained()
322//! [`poll`]: method@std::future::Future::poll
323
324cfg_rt! {
325 pub use crate::runtime::task::{JoinError, JoinHandle};
326
327 mod blocking;
328 pub use blocking::spawn_blocking;
329
330 mod spawn;
331 pub use spawn::spawn;
332
333 cfg_rt_multi_thread! {
334 pub use blocking::block_in_place;
335 }
336
337 mod yield_now;
338 pub use yield_now::yield_now;
339
340 cfg_unstable! {
341 mod consume_budget;
342 pub use consume_budget::consume_budget;
343 }
344
345 mod local;
346 pub use local::{spawn_local, LocalSet, LocalEnterGuard};
347
348 mod task_local;
349 pub use task_local::LocalKey;
350
351 mod unconstrained;
352 pub use unconstrained::{unconstrained, Unconstrained};
353
354 #[doc(inline)]
355 pub use join_set::JoinSet;
356 pub use crate::runtime::task::AbortHandle;
357
358 // Uses #[cfg(...)] instead of macro since the macro adds docsrs annotations.
359 #[cfg(not(tokio_unstable))]
360 mod join_set;
361 #[cfg(tokio_unstable)]
362 pub mod join_set;
363
364 cfg_unstable! {
365 pub use crate::runtime::task::{Id, id, try_id};
366 }
367
368 cfg_trace! {
369 mod builder;
370 pub use builder::Builder;
371 }
372
373 /// Task-related futures.
374 pub mod futures {
375 pub use super::task_local::TaskLocalFuture;
376 }
377}