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}