• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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