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