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`](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 } 208