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     pub fn block_in_place<F, R>(f: F) -> R
75     where
76         F: FnOnce() -> R,
77     {
78         crate::runtime::scheduler::block_in_place(f)
79     }
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     pub fn spawn_blocking<F, R>(f: F) -> JoinHandle<R>
203     where
204         F: FnOnce() -> R + Send + 'static,
205         R: Send + 'static,
206     {
207         crate::runtime::spawn_blocking(f)
208     }
209 }
210