diff options
author | Dan Burkert <dan@danburkert.com> | 2020-04-24 06:25:48 -0600 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-04-24 15:25:48 +0300 |
commit | d8139fef7a555f99adaa37e139787d26e24daba3 (patch) | |
tree | 5695a5fc6560ca851d12da04464747d161c55790 /tokio/src/runtime | |
parent | 9bcb50660e2d9de26a4373aaf4ab8f324c8ebbe8 (diff) |
Add Handle::block_on method (#2437)
Diffstat (limited to 'tokio/src/runtime')
-rw-r--r-- | tokio/src/runtime/enter.rs | 14 | ||||
-rw-r--r-- | tokio/src/runtime/handle.rs | 41 | ||||
-rw-r--r-- | tokio/src/runtime/mod.rs | 21 |
3 files changed, 71 insertions, 5 deletions
diff --git a/tokio/src/runtime/enter.rs b/tokio/src/runtime/enter.rs index 9b3f2ad8..ad5580cc 100644 --- a/tokio/src/runtime/enter.rs +++ b/tokio/src/runtime/enter.rs @@ -138,14 +138,11 @@ cfg_rt_threaded! { } } -cfg_blocking_impl! { - use crate::park::ParkError; - use std::time::Duration; - +cfg_block_on! { impl Enter { /// Blocks the thread on the specified future, returning the value with /// which that future completes. - pub(crate) fn block_on<F>(&mut self, mut f: F) -> Result<F::Output, ParkError> + pub(crate) fn block_on<F>(&mut self, mut f: F) -> Result<F::Output, crate::park::ParkError> where F: std::future::Future, { @@ -170,7 +167,14 @@ cfg_blocking_impl! { park.park()?; } } + } +} +cfg_blocking_impl! { + use crate::park::ParkError; + use std::time::Duration; + + impl Enter { /// Blocks the thread on the specified future for **at most** `timeout` /// /// If the future completes before `timeout`, the result is returned. If diff --git a/tokio/src/runtime/handle.rs b/tokio/src/runtime/handle.rs index db53543e..b232431b 100644 --- a/tokio/src/runtime/handle.rs +++ b/tokio/src/runtime/handle.rs @@ -119,6 +119,47 @@ cfg_rt_core! { { self.spawner.spawn(future) } + + /// Run a future to completion on the Tokio runtime from a synchronous + /// context. + /// + /// This runs the given future on the runtime, blocking until it is + /// complete, and yielding its resolved result. Any tasks or timers which + /// the future spawns internally will be executed on the runtime. + /// + /// This method should not be called from an asynchronous context. + /// + /// # Panics + /// + /// This function panics if the executor is at capacity, if the provided + /// future panics, or if called within an asynchronous execution context. + /// + /// # Examples + /// + /// ```no_run + /// use tokio::runtime::Runtime; + /// use std::thread; + /// + /// // Create the runtime + /// let rt = Runtime::new().unwrap(); + /// let handle = rt.handle().clone(); + /// + /// // Use the runtime from another thread + /// let th = thread::spawn(move || { + /// // Execute the future, blocking the current thread until completion + /// handle.block_on(async { + /// println!("hello"); + /// }); + /// }); + /// + /// th.join().unwrap(); + /// ``` + pub fn block_on<F: Future>(&self, future: F) -> F::Output { + self.enter(|| { + let mut enter = crate::runtime::enter(true); + enter.block_on(future).expect("failed to park thread") + }) + } } } diff --git a/tokio/src/runtime/mod.rs b/tokio/src/runtime/mod.rs index 2d34e2b6..293f5c93 100644 --- a/tokio/src/runtime/mod.rs +++ b/tokio/src/runtime/mod.rs @@ -402,12 +402,33 @@ impl Runtime { /// complete, and yielding its resolved result. Any tasks or timers which /// the future spawns internally will be executed on the runtime. /// + /// `&mut` is required as calling `block_on` **may** result in advancing the + /// state of the runtime. The details depend on how the runtime is + /// configured. [`runtime::Handle::block_on`][handle] provides a version + /// that takes `&self`. + /// /// This method should not be called from an asynchronous context. /// /// # Panics /// /// This function panics if the executor is at capacity, if the provided /// future panics, or if called within an asynchronous execution context. + /// + /// # Examples + /// + /// ```no_run + /// use tokio::runtime::Runtime; + /// + /// // Create the runtime + /// let mut rt = Runtime::new().unwrap(); + /// + /// // Execute the future, blocking the current thread until completion + /// rt.block_on(async { + /// println!("hello"); + /// }); + /// ``` + /// + /// [handle]: fn@Handle::block_on pub fn block_on<F: Future>(&mut self, future: F) -> F::Output { let kind = &mut self.kind; |