1 use crate::{task::JoinHandle, util::error::CONTEXT_MISSING_ERROR}; 2 3 use std::future::Future; 4 5 cfg_rt! { 6 /// Spawns a new asynchronous task, returning a 7 /// [`JoinHandle`](super::JoinHandle) for it. 8 /// 9 /// Spawning a task enables the task to execute concurrently to other tasks. The 10 /// spawned task may execute on the current thread, or it may be sent to a 11 /// different thread to be executed. The specifics depend on the current 12 /// [`Runtime`](crate::runtime::Runtime) configuration. 13 /// 14 /// There is no guarantee that a spawned task will execute to completion. 15 /// When a runtime is shutdown, all outstanding tasks are dropped, 16 /// regardless of the lifecycle of that task. 17 /// 18 /// This function must be called from the context of a Tokio runtime. Tasks running on 19 /// the Tokio runtime are always inside its context, but you can also enter the context 20 /// using the [`Runtime::enter`](crate::runtime::Runtime::enter()) method. 21 /// 22 /// # Examples 23 /// 24 /// In this example, a server is started and `spawn` is used to start a new task 25 /// that processes each received connection. 26 /// 27 /// ```no_run 28 /// use tokio::net::{TcpListener, TcpStream}; 29 /// 30 /// use std::io; 31 /// 32 /// async fn process(socket: TcpStream) { 33 /// // ... 34 /// # drop(socket); 35 /// } 36 /// 37 /// #[tokio::main] 38 /// async fn main() -> io::Result<()> { 39 /// let listener = TcpListener::bind("127.0.0.1:8080").await?; 40 /// 41 /// loop { 42 /// let (socket, _) = listener.accept().await?; 43 /// 44 /// tokio::spawn(async move { 45 /// // Process each socket concurrently. 46 /// process(socket).await 47 /// }); 48 /// } 49 /// } 50 /// ``` 51 /// 52 /// # Panics 53 /// 54 /// Panics if called from **outside** of the Tokio runtime. 55 /// 56 /// # Using `!Send` values from a task 57 /// 58 /// The task supplied to `spawn` must implement `Send`. However, it is 59 /// possible to **use** `!Send` values from the task as long as they only 60 /// exist between calls to `.await`. 61 /// 62 /// For example, this will work: 63 /// 64 /// ``` 65 /// use tokio::task; 66 /// 67 /// use std::rc::Rc; 68 /// 69 /// fn use_rc(rc: Rc<()>) { 70 /// // Do stuff w/ rc 71 /// # drop(rc); 72 /// } 73 /// 74 /// #[tokio::main] 75 /// async fn main() { 76 /// tokio::spawn(async { 77 /// // Force the `Rc` to stay in a scope with no `.await` 78 /// { 79 /// let rc = Rc::new(()); 80 /// use_rc(rc.clone()); 81 /// } 82 /// 83 /// task::yield_now().await; 84 /// }).await.unwrap(); 85 /// } 86 /// ``` 87 /// 88 /// This will **not** work: 89 /// 90 /// ```compile_fail 91 /// use tokio::task; 92 /// 93 /// use std::rc::Rc; 94 /// 95 /// fn use_rc(rc: Rc<()>) { 96 /// // Do stuff w/ rc 97 /// # drop(rc); 98 /// } 99 /// 100 /// #[tokio::main] 101 /// async fn main() { 102 /// tokio::spawn(async { 103 /// let rc = Rc::new(()); 104 /// 105 /// task::yield_now().await; 106 /// 107 /// use_rc(rc.clone()); 108 /// }).await.unwrap(); 109 /// } 110 /// ``` 111 /// 112 /// Holding on to a `!Send` value across calls to `.await` will result in 113 /// an unfriendly compile error message similar to: 114 /// 115 /// ```text 116 /// `[... some type ...]` cannot be sent between threads safely 117 /// ``` 118 /// 119 /// or: 120 /// 121 /// ```text 122 /// error[E0391]: cycle detected when processing `main` 123 /// ``` 124 #[cfg_attr(tokio_track_caller, track_caller)] 125 pub fn spawn<T>(future: T) -> JoinHandle<T::Output> 126 where 127 T: Future + Send + 'static, 128 T::Output: Send + 'static, 129 { 130 // preventing stack overflows on debug mode, by quickly sending the 131 // task to the heap. 132 if cfg!(debug_assertions) && std::mem::size_of::<T>() > 2048 { 133 spawn_inner(Box::pin(future), None) 134 } else { 135 spawn_inner(future, None) 136 } 137 } 138 139 #[cfg_attr(tokio_track_caller, track_caller)] 140 pub(super) fn spawn_inner<T>(future: T, name: Option<&str>) -> JoinHandle<T::Output> 141 where 142 T: Future + Send + 'static, 143 T::Output: Send + 'static, 144 { 145 let spawn_handle = crate::runtime::context::spawn_handle().expect(CONTEXT_MISSING_ERROR); 146 let task = crate::util::trace::task(future, "task", name); 147 spawn_handle.spawn(task) 148 } 149 } 150