Coverage Report

Created: 2026-03-31 07:04

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-1.50.0/src/task/spawn.rs
Line
Count
Source
1
use crate::runtime::BOX_FUTURE_THRESHOLD;
2
use crate::task::JoinHandle;
3
use crate::util::trace::SpawnMeta;
4
5
use std::future::Future;
6
7
cfg_rt! {
8
    /// Spawns a new asynchronous task, returning a
9
    /// [`JoinHandle`] for it.
10
    ///
11
    /// The provided future will start running in the background immediately
12
    /// when `spawn` is called, even if you don't await the returned
13
    /// [`JoinHandle`].
14
    ///
15
    /// Spawning a task enables the task to execute concurrently to other tasks. The
16
    /// spawned task may execute on the current thread, or it may be sent to a
17
    /// different thread to be executed. The specifics depend on the current
18
    /// [`Runtime`](crate::runtime::Runtime) configuration. In a
19
    /// [running runtime][running-runtime], the task will start immediately in the
20
    /// background. On a blocked runtime, the user must drive the runtime forward (for
21
    /// example, by calling [`Runtime::block_on`](crate::runtime::Runtime::block_on)).
22
    ///
23
    /// It is guaranteed that spawn will not synchronously poll the task being spawned.
24
    /// This means that calling spawn while holding a lock does not pose a risk of
25
    /// deadlocking with the spawned task.
26
    ///
27
    /// There is no guarantee that a spawned task will execute to completion.
28
    /// When a runtime is shutdown, all outstanding tasks are dropped,
29
    /// regardless of the lifecycle of that task.
30
    ///
31
    /// This function must be called from the context of a Tokio runtime. Tasks running on
32
    /// the Tokio runtime are always inside its context, but you can also enter the context
33
    /// using the [`Runtime::enter`](crate::runtime::Runtime::enter()) method.
34
    ///
35
    /// [running-runtime]: ../runtime/index.html#driving-the-runtime
36
    ///
37
    /// # Examples
38
    ///
39
    /// In this example, a server is started and `spawn` is used to start a new task
40
    /// that processes each received connection.
41
    ///
42
    /// ```no_run
43
    /// # #[cfg(not(target_family = "wasm"))]
44
    /// # {
45
    /// use tokio::net::{TcpListener, TcpStream};
46
    ///
47
    /// use std::io;
48
    ///
49
    /// async fn process(socket: TcpStream) {
50
    ///     // ...
51
    /// # drop(socket);
52
    /// }
53
    ///
54
    /// #[tokio::main]
55
    /// async fn main() -> io::Result<()> {
56
    ///     let listener = TcpListener::bind("127.0.0.1:8080").await?;
57
    ///
58
    ///     loop {
59
    ///         let (socket, _) = listener.accept().await?;
60
    ///
61
    ///         tokio::spawn(async move {
62
    ///             // Process each socket concurrently.
63
    ///             process(socket).await
64
    ///         });
65
    ///     }
66
    /// }
67
    /// # }
68
    /// ```
69
    ///
70
    /// To run multiple tasks in parallel and receive their results, join
71
    /// handles can be stored in a vector.
72
    /// ```
73
    /// # #[tokio::main(flavor = "current_thread")] async fn main() {
74
    /// async fn my_background_op(id: i32) -> String {
75
    ///     let s = format!("Starting background task {}.", id);
76
    ///     println!("{}", s);
77
    ///     s
78
    /// }
79
    ///
80
    /// let ops = vec![1, 2, 3];
81
    /// let mut tasks = Vec::with_capacity(ops.len());
82
    /// for op in ops {
83
    ///     // This call will make them start running in the background
84
    ///     // immediately.
85
    ///     tasks.push(tokio::spawn(my_background_op(op)));
86
    /// }
87
    ///
88
    /// let mut outputs = Vec::with_capacity(tasks.len());
89
    /// for task in tasks {
90
    ///     outputs.push(task.await.unwrap());
91
    /// }
92
    /// println!("{:?}", outputs);
93
    /// # }
94
    /// ```
95
    /// This example pushes the tasks to `outputs` in the order they were
96
    /// started in. If you do not care about the ordering of the outputs, then
97
    /// you can also use a [`JoinSet`].
98
    ///
99
    /// [`JoinSet`]: struct@crate::task::JoinSet
100
    ///
101
    /// # Panics
102
    ///
103
    /// Panics if called from **outside** of the Tokio runtime.
104
    ///
105
    /// # Using `!Send` values from a task
106
    ///
107
    /// The task supplied to `spawn` must implement `Send`. However, it is
108
    /// possible to **use** `!Send` values from the task as long as they only
109
    /// exist between calls to `.await`.
110
    ///
111
    /// For example, this will work:
112
    ///
113
    /// ```
114
    /// use tokio::task;
115
    ///
116
    /// use std::rc::Rc;
117
    ///
118
    /// fn use_rc(rc: Rc<()>) {
119
    ///     // Do stuff w/ rc
120
    /// # drop(rc);
121
    /// }
122
    ///
123
    /// # #[tokio::main(flavor = "current_thread")]
124
    /// # async fn main() {
125
    /// tokio::spawn(async {
126
    ///     // Force the `Rc` to stay in a scope with no `.await`
127
    ///     {
128
    ///         let rc = Rc::new(());
129
    ///         use_rc(rc.clone());
130
    ///     }
131
    ///
132
    ///     task::yield_now().await;
133
    /// }).await.unwrap();
134
    /// # }
135
    /// ```
136
    ///
137
    /// This will **not** work:
138
    ///
139
    /// ```compile_fail
140
    /// use tokio::task;
141
    ///
142
    /// use std::rc::Rc;
143
    ///
144
    /// fn use_rc(rc: Rc<()>) {
145
    ///     // Do stuff w/ rc
146
    /// # drop(rc);
147
    /// }
148
    ///
149
    /// #[tokio::main]
150
    /// async fn main() {
151
    ///     tokio::spawn(async {
152
    ///         let rc = Rc::new(());
153
    ///
154
    ///         task::yield_now().await;
155
    ///
156
    ///         use_rc(rc.clone());
157
    ///     }).await.unwrap();
158
    /// }
159
    /// ```
160
    ///
161
    /// Holding on to a `!Send` value across calls to `.await` will result in
162
    /// an unfriendly compile error message similar to:
163
    ///
164
    /// ```text
165
    /// `[... some type ...]` cannot be sent between threads safely
166
    /// ```
167
    ///
168
    /// or:
169
    ///
170
    /// ```text
171
    /// error[E0391]: cycle detected when processing `main`
172
    /// ```
173
    #[track_caller]
174
0
    pub fn spawn<F>(future: F) -> JoinHandle<F::Output>
175
0
    where
176
0
        F: Future + Send + 'static,
177
0
        F::Output: Send + 'static,
178
    {
179
0
        let fut_size = std::mem::size_of::<F>();
180
0
        if fut_size > BOX_FUTURE_THRESHOLD {
181
0
            spawn_inner(Box::pin(future), SpawnMeta::new_unnamed(fut_size))
182
        } else {
183
0
            spawn_inner(future, SpawnMeta::new_unnamed(fut_size))
184
        }
185
0
    }
186
187
    #[track_caller]
188
0
    pub(super) fn spawn_inner<T>(future: T, meta: SpawnMeta<'_>) -> JoinHandle<T::Output>
189
0
    where
190
0
        T: Future + Send + 'static,
191
0
        T::Output: Send + 'static,
192
    {
193
        use crate::runtime::{context, task};
194
195
        #[cfg(all(
196
            tokio_unstable,
197
            feature = "taskdump",
198
            feature = "rt",
199
            target_os = "linux",
200
            any(
201
                target_arch = "aarch64",
202
                target_arch = "x86",
203
                target_arch = "x86_64"
204
            )
205
        ))]
206
        let future = task::trace::Trace::root(future);
207
0
        let id = task::Id::next();
208
0
        let task = crate::util::trace::task(future, "task", meta, id.as_u64());
209
210
0
        match context::with_current(|handle| handle.spawn(task, id, meta.spawned_at)) {
211
0
            Ok(join_handle) => join_handle,
212
0
            Err(e) => panic!("{}", e),
213
        }
214
0
    }
215
}