      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
     96
     97
     98
     99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239

    //! Asynchronous green-threads.
    //!
    //! ## What are Tasks?
    //!
    //! A _task_ is a light weight, non-blocking unit of execution. A task is similar
    //! to an OS thread, but rather than being managed by the OS scheduler, they are
    //! managed by the [Tokio runtime][rt]. Another name for this general pattern is
    //! [green threads]. If you are familiar with [Go's goroutines], [Kotlin's
    //! coroutines], or [Erlang's processes], you can think of Tokio's tasks as
    //! something similar.
    //!
    //! Key points about tasks include:
    //!
    //! * Tasks are **light weight**. Because tasks are scheduled by the Tokio
    //!   runtime rather than the operating system, creating new tasks or switching
    //!   between tasks does not require a context switch and has fairly low
    //!   overhead. Creating, running, and destroying large numbers of tasks is
    //!   quite cheap, especially compared to OS threads.
    //!
    //! * Tasks are scheduled **cooperatively**. Most operating systems implement
    //!   _preemptive multitasking_. This is a scheduling technique where the
    //!   operating system allows each thread to run for a period of time, and then
    //!   _preempts_ it, temporarily pausing that thread and switching to another.
    //!   Tasks, on the other hand, implement _cooperative multitasking_. In
    //!   cooperative multitasking, a task is allowed to run until it _yields_,
    //!   indicating to the Tokio runtime's scheduler that it cannot currently
    //!   continue executing. When a task yields, the Tokio runtime switches to
    //!   executing the next task.
    //!
    //! * Tasks are **non-blocking**. Typically, when an OS thread performs I/O or
    //!   must synchronize with another thread, it _blocks_, allowing the OS to
    //!   schedule another thread. When a task cannot continue executing, it must
    //!   yield instead, allowing the Tokio runtime to schedule another task. Tasks
    //!   should generally not perform system calls or other operations that could
    //!   block a thread, as this would prevent other tasks running on the same
    //!   thread from executing as well. Instead, this module provides APIs for
    //!   running blocking operations in an asynchronous context.
    //!
    //! [rt]: crate::runtime
    //! [green threads]: https://en.wikipedia.org/wiki/Green_threads
    //! [Go's goroutines]: https://tour.golang.org/concurrency/1
    //! [Kotlin's coroutines]: https://kotlinlang.org/docs/reference/coroutines-overview.html
    //! [Erlang's processes]: http://erlang.org/doc/getting_started/conc_prog.html#processes
    //!
    //! ## Working with Tasks
    //!
    //! This module provides the following APIs for working with tasks:
    //!
    //! ### Spawning
    //!
    //! Perhaps the most important function in this module is [`task::spawn`]. This
    //! function can be thought of as an async equivalent to the standard library's
    //! [`thread::spawn`][`std::thread::spawn`]. It takes an `async` block or other
    //! [future], and creates a new task to run that work concurrently:
    //!
    //! ```
    //! use tokio::task;
    //!
    //! # async fn doc() {
    //! task::spawn(async {
    //!     // perform some work here...
    //! });
    //! # }
    //! ```
    //!
    //! Like [`std::thread::spawn`], `task::spawn` returns a [`JoinHandle`] struct.
    //! A `JoinHandle` is itself a future which may be used to await the output of
    //! the spawned task. For example:
    //!
    //! ```
    //! use tokio::task;
    //!
    //! # #[tokio::main] async fn main() -> Result<(), Box<dyn std::error::Error>> {
    //! let join = task::spawn(async {
    //!     // ...
    //!     "hello world!"
    //! });
    //!
    //! // ...
    //!
    //! // Await the result of the spawned task.
    //! let result = join.await?;
    //! assert_eq!(result, "hello world!");
    //! # Ok(())
    //! # }
    //! ```
    //!
    //! Again, like `std::thread`'s [`JoinHandle` type][thread_join], if the spawned
    //! task panics, awaiting its `JoinHandle` will return a [`JoinError`]`. For
    //! example:
    //!
    //! ```
    //! use tokio::task;
    //!
    //! # #[tokio::main] async fn main() {
    //! let join = task::spawn(async {
    //!     panic!("something bad happened!")
    //! });
    //!
    //! // The returned result indicates that the task failed.
    //! assert!(join.await.is_err());
    //! # }
    //! ```
    //!
    //! `spawn`, `JoinHandle`, and `JoinError` are present when the "rt"
    //! feature flag is enabled.
    //!
    //! [`task::spawn`]: crate::task::spawn()
    //! [future]: std::future::Future
    //! [`std::thread::spawn`]: std::thread::spawn
    //! [`JoinHandle`]: crate::task::JoinHandle
    //! [thread_join]: std::thread::JoinHandle
    //! [`JoinError`]: crate::task::JoinError
    //!
    //! ### Blocking and Yielding
    //!
    //! As we discussed above, code running in asynchronous tasks should not perform
    //! operations that can block. A blocking operation performed in a task running
    //! on a thread that is also running other tasks would block the entire thread,
    //! preventing other tasks from running.
    //!
    //! Instead, Tokio provides two APIs for running blocking operations in an
    //! asynchronous context: [`task::spawn_blocking`] and [`task::block_in_place`].
    //!
    //! #### spawn_blocking
    //!
    //! The `task::spawn_blocking` function is similar to the `task::spawn` function
    //! discussed in the previous section, but rather than spawning an
    //! _non-blocking_ future on the Tokio runtime, it instead spawns a
    //! _blocking_ function on a dedicated thread pool for blocking tasks. For
    //! example:
    //!
    //! ```
    //! use tokio::task;
    //!
    //! # async fn docs() {
    //! task::spawn_blocking(|| {
    //!     // do some compute-heavy work or call synchronous code
    //! });
    //! # }
    //! ```
    //!
    //! Just like `task::spawn`, `task::spawn_blocking` returns a `JoinHandle`
    //! which we can use to await the result of the blocking operation:
    //!
    //! ```rust
    //! # use tokio::task;
    //! # async fn docs() -> Result<(), Box<dyn std::error::Error>>{
    //! let join = task::spawn_blocking(|| {
    //!     // do some compute-heavy work or call synchronous code
    //!     "blocking completed"
    //! });
    //!
    //! let result = join.await?;
    //! assert_eq!(result, "blocking completed");
    //! # Ok(())
    //! # }
    //! ```
    //!
    //! #### block_in_place
    //!
    //! When using the [multi-threaded runtime][rt-multi-thread], the [`task::block_in_place`]
    //! function is also available. Like `task::spawn_blocking`, this function
    //! allows running a blocking operation from an asynchronous context. Unlike
    //! `spawn_blocking`, however, `block_in_place` works by transitioning the
    //! _current_ worker thread to a blocking thread, moving other tasks running on
    //! that thread to another worker thread. This can improve performance by avoiding
    //! context switches.
    //!
    //! For example:
    //!
    //! ```
    //! use tokio::task;
    //!
    //! # async fn docs() {
    //! let result = task::block_in_place(|| {
    //!     // do some compute-heavy work or call synchronous code
    //!     "blocking completed"
    //! });
    //!
    //! assert_eq!(result, "blocking completed");
    //! # }
    //! ```
    //!
    //! #### yield_now
    //!
    //! In addition, this module provides a [`task::yield_now`] async function
    //! that is analogous to the standard library's [`thread::yield_now`]. Calling
    //! and `await`ing this function will cause the current task to yield to the
    //! Tokio runtime's scheduler, allowing other tasks to be
    //! scheduled. Eventually, the yielding task will be polled again, allowing it
    //! to execute. For example:
    //!
    //! ```rust
    //! use tokio::task;
    //!
    //! # #[tokio::main] async fn main() {
    //! async {
    //!     task::spawn(async {
    //!         // ...
    //!         println!("spawned task done!")
    //!     });
    //!
    //!     // Yield, allowing the newly-spawned task to execute first.
    //!     task::yield_now().await;
    //!     println!("main task done!");
    //! }
    //! # .await;
    //! # }
    //! ```
    //!
    //! [`task::spawn_blocking`]: crate::task::spawn_blocking
    //! [`task::block_in_place`]: crate::task::block_in_place
    //! [rt-multi-thread]: ../runtime/index.html#threaded-scheduler
    //! [`task::yield_now`]: crate::task::yield_now()
    //! [`thread::yield_now`]: std::thread::yield_now

    cfg_rt! {
        pub use crate::runtime::task::{JoinError, JoinHandle};

        mod blocking;
        pub use blocking::spawn_blocking;

        mod spawn;
        pub use spawn::spawn;

        cfg_rt_multi_thread! {
            pub use blocking::block_in_place;
        }

        mod yield_now;
        pub use yield_now::yield_now;

        mod local;
        pub use local::{spawn_local, LocalSet};

        mod task_local;
        pub use task_local::LocalKey;
    }