|
1 | 1 | use crate::runtime::{blocking, context, io, time, Spawner};
|
2 | 2 | use std::{error, fmt};
|
3 | 3 |
|
| 4 | +cfg_blocking! { |
| 5 | + use crate::runtime::task; |
| 6 | + use crate::runtime::blocking::task::BlockingTask; |
| 7 | +} |
| 8 | + |
4 | 9 | cfg_rt_core! {
|
5 | 10 | use crate::task::JoinHandle;
|
6 | 11 |
|
@@ -263,6 +268,79 @@ cfg_rt_core! {
|
263 | 268 | }
|
264 | 269 | }
|
265 | 270 |
|
| 271 | +cfg_blocking! { |
| 272 | + impl Handle { |
| 273 | + /// Runs the provided closure on a thread where blocking is acceptable. |
| 274 | + /// |
| 275 | + /// In general, issuing a blocking call or performing a lot of compute in a |
| 276 | + /// future without yielding is not okay, as it may prevent the executor from |
| 277 | + /// driving other futures forward. This function runs the provided closure |
| 278 | + /// on a thread dedicated to blocking operations. See the [CPU-bound tasks |
| 279 | + /// and blocking code][blocking] section for more information. |
| 280 | + /// |
| 281 | + /// Tokio will spawn more blocking threads when they are requested through |
| 282 | + /// this function until the upper limit configured on the [`Builder`] is |
| 283 | + /// reached. This limit is very large by default, because `spawn_blocking` is |
| 284 | + /// often used for various kinds of IO operations that cannot be performed |
| 285 | + /// asynchronously. When you run CPU-bound code using `spawn_blocking`, you |
| 286 | + /// should keep this large upper limit in mind; to run your CPU-bound |
| 287 | + /// computations on only a few threads, you should use a separate thread |
| 288 | + /// pool such as [rayon] rather than configuring the number of blocking |
| 289 | + /// threads. |
| 290 | + /// |
| 291 | + /// This function is intended for non-async operations that eventually |
| 292 | + /// finish on their own. If you want to spawn an ordinary thread, you should |
| 293 | + /// use [`thread::spawn`] instead. |
| 294 | + /// |
| 295 | + /// Closures spawned using `spawn_blocking` cannot be cancelled. When you |
| 296 | + /// shut down the executor, it will wait indefinitely for all blocking |
| 297 | + /// operations to finish. You can use [`shutdown_timeout`] to stop waiting |
| 298 | + /// for them after a certain timeout. Be aware that this will still not |
| 299 | + /// cancel the tasks — they are simply allowed to keep running after the |
| 300 | + /// method returns. |
| 301 | + /// |
| 302 | + /// Note that if you are using the [basic scheduler], this function will |
| 303 | + /// still spawn additional threads for blocking operations. The basic |
| 304 | + /// scheduler's single thread is only used for asynchronous code. |
| 305 | + /// |
| 306 | + /// [`Builder`]: struct@crate::runtime::Builder |
| 307 | + /// [blocking]: ../index.html#cpu-bound-tasks-and-blocking-code |
| 308 | + /// [rayon]: https://docs.rs/rayon |
| 309 | + /// [basic scheduler]: fn@crate::runtime::Builder::basic_scheduler |
| 310 | + /// [`thread::spawn`]: fn@std::thread::spawn |
| 311 | + /// [`shutdown_timeout`]: fn@crate::runtime::Runtime::shutdown_timeout |
| 312 | + /// |
| 313 | + /// # Examples |
| 314 | + /// |
| 315 | + /// ``` |
| 316 | + /// use tokio::runtime::Runtime; |
| 317 | + /// |
| 318 | + /// # async fn docs() -> Result<(), Box<dyn std::error::Error>>{ |
| 319 | + /// // Create the runtime |
| 320 | + /// let rt = Runtime::new().unwrap(); |
| 321 | + /// let handle = rt.handle(); |
| 322 | + /// |
| 323 | + /// let res = handle.spawn_blocking(move || { |
| 324 | + /// // do some compute-heavy work or call synchronous code |
| 325 | + /// "done computing" |
| 326 | + /// }).await?; |
| 327 | + /// |
| 328 | + /// assert_eq!(res, "done computing"); |
| 329 | + /// # Ok(()) |
| 330 | + /// # } |
| 331 | + /// ``` |
| 332 | + pub fn spawn_blocking<F, R>(&self, f: F) -> JoinHandle<R> |
| 333 | + where |
| 334 | + F: FnOnce() -> R + Send + 'static, |
| 335 | + R: Send + 'static, |
| 336 | + { |
| 337 | + let (task, handle) = task::joinable(BlockingTask::new(f)); |
| 338 | + let _ = self.blocking_spawner.spawn(task, self); |
| 339 | + handle |
| 340 | + } |
| 341 | + } |
| 342 | +} |
| 343 | + |
266 | 344 | /// Error returned by `try_current` when no Runtime has been started
|
267 | 345 | pub struct TryCurrentError(());
|
268 | 346 |
|
|
0 commit comments