1 #![allow(unreachable_pub)] 2 use crate::{ 3 runtime::Handle, 4 task::{JoinHandle, LocalSet}, 5 }; 6 use std::{future::Future, io}; 7 8 /// Factory which is used to configure the properties of a new task. 9 /// 10 /// **Note**: This is an [unstable API][unstable]. The public API of this type 11 /// may break in 1.x releases. See [the documentation on unstable 12 /// features][unstable] for details. 13 /// 14 /// Methods can be chained in order to configure it. 15 /// 16 /// Currently, there is only one configuration option: 17 /// 18 /// - [`name`], which specifies an associated name for 19 /// the task 20 /// 21 /// There are three types of task that can be spawned from a Builder: 22 /// - [`spawn_local`] for executing futures on the current thread 23 /// - [`spawn`] for executing [`Send`] futures on the runtime 24 /// - [`spawn_blocking`] for executing blocking code in the 25 /// blocking thread pool. 26 /// 27 /// ## Example 28 /// 29 /// ```no_run 30 /// use tokio::net::{TcpListener, TcpStream}; 31 /// 32 /// use std::io; 33 /// 34 /// async fn process(socket: TcpStream) { 35 /// // ... 36 /// # drop(socket); 37 /// } 38 /// 39 /// #[tokio::main] 40 /// async fn main() -> io::Result<()> { 41 /// let listener = TcpListener::bind("127.0.0.1:8080").await?; 42 /// 43 /// loop { 44 /// let (socket, _) = listener.accept().await?; 45 /// 46 /// tokio::task::Builder::new() 47 /// .name("tcp connection handler") 48 /// .spawn(async move { 49 /// // Process each socket concurrently. 50 /// process(socket).await 51 /// })?; 52 /// } 53 /// } 54 /// ``` 55 /// [unstable]: crate#unstable-features 56 /// [`name`]: Builder::name 57 /// [`spawn_local`]: Builder::spawn_local 58 /// [`spawn`]: Builder::spawn 59 /// [`spawn_blocking`]: Builder::spawn_blocking 60 #[derive(Default, Debug)] 61 #[cfg_attr(docsrs, doc(cfg(all(tokio_unstable, feature = "tracing"))))] 62 pub struct Builder<'a> { 63 name: Option<&'a str>, 64 } 65 66 impl<'a> Builder<'a> { 67 /// Creates a new task builder. new() -> Self68 pub fn new() -> Self { 69 Self::default() 70 } 71 72 /// Assigns a name to the task which will be spawned. name(&self, name: &'a str) -> Self73 pub fn name(&self, name: &'a str) -> Self { 74 Self { name: Some(name) } 75 } 76 77 /// Spawns a task with this builder's settings on the current runtime. 78 /// 79 /// # Panics 80 /// 81 /// This method panics if called outside of a Tokio runtime. 82 /// 83 /// See [`task::spawn`](crate::task::spawn()) for 84 /// more details. 85 #[track_caller] spawn<Fut>(self, future: Fut) -> io::Result<JoinHandle<Fut::Output>> where Fut: Future + Send + 'static, Fut::Output: Send + 'static,86 pub fn spawn<Fut>(self, future: Fut) -> io::Result<JoinHandle<Fut::Output>> 87 where 88 Fut: Future + Send + 'static, 89 Fut::Output: Send + 'static, 90 { 91 Ok(super::spawn::spawn_inner(future, self.name)) 92 } 93 94 /// Spawn a task with this builder's settings on the provided [runtime 95 /// handle]. 96 /// 97 /// See [`Handle::spawn`] for more details. 98 /// 99 /// [runtime handle]: crate::runtime::Handle 100 /// [`Handle::spawn`]: crate::runtime::Handle::spawn 101 #[track_caller] spawn_on<Fut>(self, future: Fut, handle: &Handle) -> io::Result<JoinHandle<Fut::Output>> where Fut: Future + Send + 'static, Fut::Output: Send + 'static,102 pub fn spawn_on<Fut>(self, future: Fut, handle: &Handle) -> io::Result<JoinHandle<Fut::Output>> 103 where 104 Fut: Future + Send + 'static, 105 Fut::Output: Send + 'static, 106 { 107 Ok(handle.spawn_named(future, self.name)) 108 } 109 110 /// Spawns `!Send` a task on the current [`LocalSet`] with this builder's 111 /// settings. 112 /// 113 /// The spawned future will be run on the same thread that called `spawn_local`. 114 /// This may only be called from the context of a [local task set][`LocalSet`]. 115 /// 116 /// # Panics 117 /// 118 /// This function panics if called outside of a [local task set][`LocalSet`]. 119 /// 120 /// See [`task::spawn_local`] for more details. 121 /// 122 /// [`task::spawn_local`]: crate::task::spawn_local 123 /// [`LocalSet`]: crate::task::LocalSet 124 #[track_caller] spawn_local<Fut>(self, future: Fut) -> io::Result<JoinHandle<Fut::Output>> where Fut: Future + 'static, Fut::Output: 'static,125 pub fn spawn_local<Fut>(self, future: Fut) -> io::Result<JoinHandle<Fut::Output>> 126 where 127 Fut: Future + 'static, 128 Fut::Output: 'static, 129 { 130 Ok(super::local::spawn_local_inner(future, self.name)) 131 } 132 133 /// Spawns `!Send` a task on the provided [`LocalSet`] with this builder's 134 /// settings. 135 /// 136 /// See [`LocalSet::spawn_local`] for more details. 137 /// 138 /// [`LocalSet::spawn_local`]: crate::task::LocalSet::spawn_local 139 /// [`LocalSet`]: crate::task::LocalSet 140 #[track_caller] spawn_local_on<Fut>( self, future: Fut, local_set: &LocalSet, ) -> io::Result<JoinHandle<Fut::Output>> where Fut: Future + 'static, Fut::Output: 'static,141 pub fn spawn_local_on<Fut>( 142 self, 143 future: Fut, 144 local_set: &LocalSet, 145 ) -> io::Result<JoinHandle<Fut::Output>> 146 where 147 Fut: Future + 'static, 148 Fut::Output: 'static, 149 { 150 Ok(local_set.spawn_named(future, self.name)) 151 } 152 153 /// Spawns blocking code on the blocking threadpool. 154 /// 155 /// # Panics 156 /// 157 /// This method panics if called outside of a Tokio runtime. 158 /// 159 /// See [`task::spawn_blocking`](crate::task::spawn_blocking) 160 /// for more details. 161 #[track_caller] spawn_blocking<Function, Output>( self, function: Function, ) -> io::Result<JoinHandle<Output>> where Function: FnOnce() -> Output + Send + 'static, Output: Send + 'static,162 pub fn spawn_blocking<Function, Output>( 163 self, 164 function: Function, 165 ) -> io::Result<JoinHandle<Output>> 166 where 167 Function: FnOnce() -> Output + Send + 'static, 168 Output: Send + 'static, 169 { 170 let handle = Handle::current(); 171 self.spawn_blocking_on(function, &handle) 172 } 173 174 /// Spawns blocking code on the provided [runtime handle]'s blocking threadpool. 175 /// 176 /// See [`Handle::spawn_blocking`] for more details. 177 /// 178 /// [runtime handle]: crate::runtime::Handle 179 /// [`Handle::spawn_blocking`]: crate::runtime::Handle::spawn_blocking 180 #[track_caller] spawn_blocking_on<Function, Output>( self, function: Function, handle: &Handle, ) -> io::Result<JoinHandle<Output>> where Function: FnOnce() -> Output + Send + 'static, Output: Send + 'static,181 pub fn spawn_blocking_on<Function, Output>( 182 self, 183 function: Function, 184 handle: &Handle, 185 ) -> io::Result<JoinHandle<Output>> 186 where 187 Function: FnOnce() -> Output + Send + 'static, 188 Output: Send + 'static, 189 { 190 use crate::runtime::Mandatory; 191 let (join_handle, spawn_result) = handle.inner.blocking_spawner().spawn_blocking_inner( 192 function, 193 Mandatory::NonMandatory, 194 self.name, 195 handle, 196 ); 197 198 spawn_result?; 199 Ok(join_handle) 200 } 201 } 202