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