Coverage Report

Created: 2025-02-25 06:39

/rust/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.43.0/src/task/blocking.rs
Line
Count
Source (jump to first uncovered line)
1
use crate::task::JoinHandle;
2
3
cfg_rt_multi_thread! {
4
    /// Runs the provided blocking function on the current thread without
5
    /// blocking the executor.
6
    ///
7
    /// In general, issuing a blocking call or performing a lot of compute in a
8
    /// future without yielding is problematic, as it may prevent the executor
9
    /// from driving other tasks forward. Calling this function informs the
10
    /// executor that the currently executing task is about to block the thread,
11
    /// so the executor is able to hand off any other tasks it has to a new
12
    /// worker thread before that happens. See the [CPU-bound tasks and blocking
13
    /// code][blocking] section for more information.
14
    ///
15
    /// Be aware that although this function avoids starving other independently
16
    /// spawned tasks, any other code running concurrently in the same task will
17
    /// be suspended during the call to `block_in_place`. This can happen e.g.
18
    /// when using the [`join!`] macro. To avoid this issue, use
19
    /// [`spawn_blocking`] instead of `block_in_place`.
20
    ///
21
    /// Note that this function cannot be used within a [`current_thread`] runtime
22
    /// because in this case there are no other worker threads to hand off tasks
23
    /// to. On the other hand, calling the function outside a runtime is
24
    /// allowed. In this case, `block_in_place` just calls the provided closure
25
    /// normally.
26
    ///
27
    /// Code running behind `block_in_place` cannot be cancelled. When you shut
28
    /// down the executor, it will wait indefinitely for all blocking operations
29
    /// to finish. You can use [`shutdown_timeout`] to stop waiting for them
30
    /// after a certain timeout. Be aware that this will still not cancel the
31
    /// tasks — they are simply allowed to keep running after the method
32
    /// returns.
33
    ///
34
    /// [blocking]: ../index.html#cpu-bound-tasks-and-blocking-code
35
    /// [`spawn_blocking`]: fn@crate::task::spawn_blocking
36
    /// [`join!`]: macro@join
37
    /// [`thread::spawn`]: fn@std::thread::spawn
38
    /// [`shutdown_timeout`]: fn@crate::runtime::Runtime::shutdown_timeout
39
    ///
40
    /// # Examples
41
    ///
42
    /// ```
43
    /// use tokio::task;
44
    ///
45
    /// # async fn docs() {
46
    /// task::block_in_place(move || {
47
    ///     // do some compute-heavy work or call synchronous code
48
    /// });
49
    /// # }
50
    /// ```
51
    ///
52
    /// Code running inside `block_in_place` may use `block_on` to reenter the
53
    /// async context.
54
    ///
55
    /// ```
56
    /// use tokio::task;
57
    /// use tokio::runtime::Handle;
58
    ///
59
    /// # async fn docs() {
60
    /// task::block_in_place(move || {
61
    ///     Handle::current().block_on(async move {
62
    ///         // do something async
63
    ///     });
64
    /// });
65
    /// # }
66
    /// ```
67
    ///
68
    /// # Panics
69
    ///
70
    /// This function panics if called from a [`current_thread`] runtime.
71
    ///
72
    /// [`current_thread`]: fn@crate::runtime::Builder::new_current_thread
73
    #[track_caller]
74
0
    pub fn block_in_place<F, R>(f: F) -> R
75
0
    where
76
0
        F: FnOnce() -> R,
77
0
    {
78
0
        crate::runtime::scheduler::block_in_place(f)
79
0
    }
80
}
81
82
cfg_rt! {
83
    /// Runs the provided closure on a thread where blocking is acceptable.
84
    ///
85
    /// In general, issuing a blocking call or performing a lot of compute in a
86
    /// future without yielding is problematic, as it may prevent the executor from
87
    /// driving other futures forward. This function runs the provided closure on a
88
    /// thread dedicated to blocking operations. See the [CPU-bound tasks and
89
    /// blocking code][blocking] section for more information.
90
    ///
91
    /// Tokio will spawn more blocking threads when they are requested through this
92
    /// function until the upper limit configured on the [`Builder`] is reached.
93
    /// After reaching the upper limit, the tasks are put in a queue.
94
    /// The thread limit is very large by default, because `spawn_blocking` is often
95
    /// used for various kinds of IO operations that cannot be performed
96
    /// asynchronously.  When you run CPU-bound code using `spawn_blocking`, you
97
    /// should keep this large upper limit in mind. When running many CPU-bound
98
    /// computations, a semaphore or some other synchronization primitive should be
99
    /// used to limit the number of computation executed in parallel. Specialized
100
    /// CPU-bound executors, such as [rayon], may also be a good fit.
101
    ///
102
    /// This function is intended for non-async operations that eventually finish on
103
    /// their own. If you want to spawn an ordinary thread, you should use
104
    /// [`thread::spawn`] instead.
105
    ///
106
    /// Be aware that tasks spawned using `spawn_blocking` cannot be aborted
107
    /// because they are not async. If you call [`abort`] on a `spawn_blocking`
108
    /// task, then this *will not have any effect*, and the task will continue
109
    /// running normally. The exception is if the task has not started running
110
    /// yet; in that case, calling `abort` may prevent the task from starting.
111
    ///
112
    /// When you shut down the executor, it will wait indefinitely for all blocking operations to
113
    /// finish. You can use [`shutdown_timeout`] to stop waiting for them after a
114
    /// certain timeout. Be aware that this will still not cancel the tasks — they
115
    /// are simply allowed to keep running after the method returns.  It is possible
116
    /// for a blocking task to be cancelled if it has not yet started running, but this
117
    /// is not guaranteed.
118
    ///
119
    /// Note that if you are using the single threaded runtime, this function will
120
    /// still spawn additional threads for blocking operations. The current-thread
121
    /// scheduler's single thread is only used for asynchronous code.
122
    ///
123
    /// # Related APIs and patterns for bridging asynchronous and blocking code
124
    ///
125
    /// In simple cases, it is sufficient to have the closure accept input
126
    /// parameters at creation time and return a single value (or struct/tuple, etc.).
127
    ///
128
    /// For more complex situations in which it is desirable to stream data to or from
129
    /// the synchronous context, the [`mpsc channel`] has `blocking_send` and
130
    /// `blocking_recv` methods for use in non-async code such as the thread created
131
    /// by `spawn_blocking`.
132
    ///
133
    /// Another option is [`SyncIoBridge`] for cases where the synchronous context
134
    /// is operating on byte streams.  For example, you might use an asynchronous
135
    /// HTTP client such as [hyper] to fetch data, but perform complex parsing
136
    /// of the payload body using a library written for synchronous I/O.
137
    ///
138
    /// Finally, see also [Bridging with sync code][bridgesync] for discussions
139
    /// around the opposite case of using Tokio as part of a larger synchronous
140
    /// codebase.
141
    ///
142
    /// [`Builder`]: struct@crate::runtime::Builder
143
    /// [blocking]: ../index.html#cpu-bound-tasks-and-blocking-code
144
    /// [rayon]: https://docs.rs/rayon
145
    /// [`mpsc channel`]: crate::sync::mpsc
146
    /// [`SyncIoBridge`]: https://docs.rs/tokio-util/latest/tokio_util/io/struct.SyncIoBridge.html
147
    /// [hyper]: https://docs.rs/hyper
148
    /// [`thread::spawn`]: fn@std::thread::spawn
149
    /// [`shutdown_timeout`]: fn@crate::runtime::Runtime::shutdown_timeout
150
    /// [bridgesync]: https://tokio.rs/tokio/topics/bridging
151
    /// [`AtomicBool`]: struct@std::sync::atomic::AtomicBool
152
    /// [`abort`]: crate::task::JoinHandle::abort
153
    ///
154
    /// # Examples
155
    ///
156
    /// Pass an input value and receive result of computation:
157
    ///
158
    /// ```
159
    /// use tokio::task;
160
    ///
161
    /// # async fn docs() -> Result<(), Box<dyn std::error::Error>>{
162
    /// // Initial input
163
    /// let mut v = "Hello, ".to_string();
164
    /// let res = task::spawn_blocking(move || {
165
    ///     // Stand-in for compute-heavy work or using synchronous APIs
166
    ///     v.push_str("world");
167
    ///     // Pass ownership of the value back to the asynchronous context
168
    ///     v
169
    /// }).await?;
170
    ///
171
    /// // `res` is the value returned from the thread
172
    /// assert_eq!(res.as_str(), "Hello, world");
173
    /// # Ok(())
174
    /// # }
175
    /// ```
176
    ///
177
    /// Use a channel:
178
    ///
179
    /// ```
180
    /// use tokio::task;
181
    /// use tokio::sync::mpsc;
182
    ///
183
    /// # async fn docs() {
184
    /// let (tx, mut rx) = mpsc::channel(2);
185
    /// let start = 5;
186
    /// let worker = task::spawn_blocking(move || {
187
    ///     for x in 0..10 {
188
    ///         // Stand in for complex computation
189
    ///         tx.blocking_send(start + x).unwrap();
190
    ///     }
191
    /// });
192
    ///
193
    /// let mut acc = 0;
194
    /// while let Some(v) = rx.recv().await {
195
    ///     acc += v;
196
    /// }
197
    /// assert_eq!(acc, 95);
198
    /// worker.await.unwrap();
199
    /// # }
200
    /// ```
201
    #[track_caller]
202
0
    pub fn spawn_blocking<F, R>(f: F) -> JoinHandle<R>
203
0
    where
204
0
        F: FnOnce() -> R + Send + 'static,
205
0
        R: Send + 'static,
206
0
    {
207
0
        crate::runtime::spawn_blocking(f)
208
0
    }
Unexecuted instantiation: tokio::task::blocking::spawn_blocking::<<hyper_util::client::legacy::connect::dns::GaiResolver as tower_service::Service<hyper_util::client::legacy::connect::dns::Name>>::call::{closure#0}, core::result::Result<hyper_util::client::legacy::connect::dns::SocketAddrs, std::io::error::Error>>
Unexecuted instantiation: tokio::task::blocking::spawn_blocking::<_, _>
209
}