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
//! Types and traits for working with asynchronous tasks.
//!
//! This module is similar to [`std::thread`], except it uses asynchronous tasks in place of
//! threads.
//!
//! [`std::thread`]: https://doc.rust-lang.org/std/thread
//!
//! ## The task model
//!
//! An executing asynchronous Rust program consists of a collection of native OS threads, on top of
//! which multiple stackless coroutines are multiplexed. We refer to these as "tasks".  Tasks can
//! be named, and provide some built-in support for synchronization.
//!
//! Communication between tasks can be done through channels, Rust's message-passing types, along
//! with [other forms of tasks synchronization](../sync/index.html) and shared-memory data
//! structures. In particular, types that are guaranteed to be threadsafe are easily shared between
//! tasks using the atomically-reference-counted container, [`Arc`].
//!
//! Fatal logic errors in Rust cause *thread panic*, during which a thread will unwind the stack,
//! running destructors and freeing owned resources. If a panic occurs inside a task, there is no
//! meaningful way of recovering, so the panic will propagate through any thread boundaries all the
//! way to the root task. This is also known as a "panic = abort" model.
//!
//! ## Spawning a task
//!
//! A new task can be spawned using the [`task::spawn`][`spawn`] function:
//!
//! ```no_run
//! use async_std::task;
//!
//! task::spawn(async {
//!     // some work here
//! });
//! ```
//!
//! In this example, the spawned task is "detached" from the current task. This means that it can
//! outlive its parent (the task that spawned it), unless this parent is the root task.
//!
//! The root task can also wait on the completion of the child task; a call to [`spawn`] produces a
//! [`JoinHandle`], which provides implements `Future` and can be `await`ed:
//!
//! ```
//! use async_std::task;
//!
//! # async_std::task::block_on(async {
//! #
//! let child = task::spawn(async {
//!     // some work here
//! });
//! // some work here
//! let res = child.await;
//! #
//! # })
//! ```
//!
//! The `await` operator returns the final value produced by the child task.
//!
//! ## Configuring tasks
//!
//! A new task can be configured before it is spawned via the [`Builder`] type,
//! which currently allows you to set the name and stack size for the child task:
//!
//! ```
//! # #![allow(unused_must_use)]
//! use async_std::task;
//!
//! # async_std::task::block_on(async {
//! #
//! task::Builder::new().name("child1".to_string()).spawn(async {
//!     println!("Hello, world!");
//! });
//! #
//! # })
//! ```
//!
//! ## The `Task` type
//!
//! Tasks are represented via the [`Task`] type, which you can get in one of
//! two ways:
//!
//! * By spawning a new task, e.g., using the [`task::spawn`][`spawn`]
//!   function, and calling [`task`][`JoinHandle::task`] on the [`JoinHandle`].
//! * By requesting the current task, using the [`task::current`] function.
//!
//! ## Task-local storage
//!
//! This module also provides an implementation of task-local storage for Rust
//! programs. Task-local storage is a method of storing data into a global
//! variable that each task in the program will have its own copy of.
//! Tasks do not share this data, so accesses do not need to be synchronized.
//!
//! A task-local key owns the value it contains and will destroy the value when the
//! task exits. It is created with the [`task_local!`] macro and can contain any
//! value that is `'static` (no borrowed pointers). It provides an accessor function,
//! [`with`], that yields a shared reference to the value to the specified
//! closure. Task-local keys allow only shared access to values, as there would be no
//! way to guarantee uniqueness if mutable borrows were allowed.
//!
//! ## Naming tasks
//!
//! Tasks are able to have associated names for identification purposes. By default, spawned
//! tasks are unnamed. To specify a name for a task, build the task with [`Builder`] and pass
//! the desired task name to [`Builder::name`]. To retrieve the task name from within the
//! task, use [`Task::name`].
//!
//! [`Arc`]: ../gsync/struct.Arc.html
//! [`spawn`]: fn.spawn.html
//! [`JoinHandle`]: struct.JoinHandle.html
//! [`JoinHandle::task`]: struct.JoinHandle.html#method.task
//! [`join`]: struct.JoinHandle.html#method.join
//! [`panic!`]: https://doc.rust-lang.org/std/macro.panic.html
//! [`Builder`]: struct.Builder.html
//! [`Builder::stack_size`]: struct.Builder.html#method.stack_size
//! [`Builder::name`]: struct.Builder.html#method.name
//! [`task::current`]: fn.current.html
//! [`Task`]: struct.Thread.html
//! [`Task::name`]: struct.Task.html#method.name
//! [`task_local!`]: ../macro.task_local.html
//! [`with`]: struct.LocalKey.html#method.with

#[doc(inline)]
pub use std::task::{Context, Poll, Waker};

#[doc(inline)]
pub use async_macros::ready;

pub use block_on::block_on;
pub use builder::Builder;
pub use pool::spawn;
pub use sleep::sleep;
pub use task::{JoinHandle, Task, TaskId};
pub use task_local::{AccessError, LocalKey};
pub use worker::current;

mod block_on;
mod builder;
mod pool;
mod sleep;
mod sleepers;
mod task;
mod task_local;
mod worker;

pub(crate) mod blocking;

cfg_if::cfg_if! {
    if #[cfg(any(feature = "unstable", feature = "docs"))] {
        mod yield_now;
        pub use yield_now::yield_now;
    }
}

/// Spawns a blocking task.
///
/// The task will be spawned onto a thread pool specifically dedicated to blocking tasks. This
/// is useful to prevent long-running synchronous operations from blocking the main futures
/// executor.
///
/// See also: [`task::block_on`], [`task::spawn`].
///
/// [`task::block_on`]: fn.block_on.html
/// [`task::spawn`]: fn.spawn.html
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// # async_std::task::block_on(async {
/// #
/// use async_std::task;
///
/// task::spawn_blocking(|| {
///     println!("long-running task here");
/// }).await;
/// #
/// # })
/// ```
// Once this function stabilizes we should merge `blocking::spawn` into this so
// all code in our crate uses `task::blocking` too.
#[cfg(any(feature = "unstable", feature = "docs"))]
#[cfg_attr(feature = "docs", doc(cfg(unstable)))]
#[inline]
pub fn spawn_blocking<F, R>(f: F) -> task::JoinHandle<R>
where
    F: FnOnce() -> R + Send + 'static,
    R: Send + 'static,
{
    blocking::spawn(f)
}