madsim_real_tokio/task/builder.rs
1#![allow(unreachable_pub)]
2use crate::{
3 runtime::Handle,
4 task::{JoinHandle, LocalSet},
5};
6use 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"))))]
62pub struct Builder<'a> {
63 name: Option<&'a str>,
64}
65
66impl<'a> Builder<'a> {
67 /// Creates a new task builder.
68 pub fn new() -> Self {
69 Self::default()
70 }
71
72 /// Assigns a name to the task which will be spawned.
73 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]
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]
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]
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]
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]
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]
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}