diff options
author | Jeff Vander Stoep <jeffv@google.com> | 2021-11-16 11:16:30 +0100 |
---|---|---|
committer | Jeff Vander Stoep <jeffv@google.com> | 2021-11-16 11:17:30 +0100 |
commit | 1db412d2c35d13b9d4b8ab28ca56de5b77abff71 (patch) | |
tree | a86a1094890ceb522b599e1f37f24c2e16239fd3 /src/runtime/handle.rs | |
parent | e16ac718df3b8af3bef9bc0c1b6c9bfb5f8e71e1 (diff) | |
download | tokio-1db412d2c35d13b9d4b8ab28ca56de5b77abff71.tar.gz |
Update to 1.14.0
Test: atest
Change-Id: I713529f5ba957c212f50bde27b4428612dbcdefd
Diffstat (limited to 'src/runtime/handle.rs')
-rw-r--r-- | src/runtime/handle.rs | 92 |
1 files changed, 75 insertions, 17 deletions
diff --git a/src/runtime/handle.rs b/src/runtime/handle.rs index bad6a00..cd1cb76 100644 --- a/src/runtime/handle.rs +++ b/src/runtime/handle.rs @@ -1,9 +1,10 @@ use crate::runtime::blocking::{BlockingTask, NoopSchedule}; use crate::runtime::task::{self, JoinHandle}; use crate::runtime::{blocking, context, driver, Spawner}; -use crate::util::error::CONTEXT_MISSING_ERROR; +use crate::util::error::{CONTEXT_MISSING_ERROR, THREAD_LOCAL_DESTROYED_ERROR}; use std::future::Future; +use std::marker::PhantomData; use std::{error, fmt}; /// Handle to the runtime. @@ -17,15 +18,25 @@ pub struct Handle { pub(super) spawner: Spawner, /// Handles to the I/O drivers + #[cfg_attr( + not(any(feature = "net", feature = "process", all(unix, feature = "signal"))), + allow(dead_code) + )] pub(super) io_handle: driver::IoHandle, /// Handles to the signal drivers + #[cfg_attr( + not(any(feature = "signal", all(unix, feature = "process"))), + allow(dead_code) + )] pub(super) signal_handle: driver::SignalHandle, /// Handles to the time drivers + #[cfg_attr(not(feature = "time"), allow(dead_code))] pub(super) time_handle: driver::TimeHandle, /// Source of `Instant::now()` + #[cfg_attr(not(all(feature = "time", feature = "test-util")), allow(dead_code))] pub(super) clock: driver::Clock, /// Blocking pool spawner @@ -41,12 +52,12 @@ pub struct Handle { #[derive(Debug)] #[must_use = "Creating and dropping a guard does nothing"] pub struct EnterGuard<'a> { - handle: &'a Handle, - guard: context::EnterGuard, + _guard: context::EnterGuard, + _handle_lifetime: PhantomData<&'a Handle>, } impl Handle { - /// Enter the runtime context. This allows you to construct types that must + /// Enters the runtime context. This allows you to construct types that must /// have an executor available on creation such as [`Sleep`] or [`TcpStream`]. /// It will also allow you to call methods such as [`tokio::spawn`]. /// @@ -55,12 +66,12 @@ impl Handle { /// [`tokio::spawn`]: fn@crate::spawn pub fn enter(&self) -> EnterGuard<'_> { EnterGuard { - handle: self, - guard: context::enter(self.clone()), + _guard: context::enter(self.clone()), + _handle_lifetime: PhantomData, } } - /// Returns a `Handle` view over the currently running `Runtime` + /// Returns a `Handle` view over the currently running `Runtime`. /// /// # Panic /// @@ -99,7 +110,7 @@ impl Handle { /// # } /// ``` pub fn current() -> Self { - context::current().expect(CONTEXT_MISSING_ERROR) + context::current() } /// Returns a Handle view over the currently running Runtime @@ -108,7 +119,7 @@ impl Handle { /// /// Contrary to `current`, this never panics pub fn try_current() -> Result<Self, TryCurrentError> { - context::current().ok_or(TryCurrentError(())) + context::try_current() } cfg_stats! { @@ -119,7 +130,7 @@ impl Handle { } } - /// Spawn a future onto the Tokio runtime. + /// Spawns a future onto the Tokio runtime. /// /// This spawns the given future onto the runtime's executor, usually a /// thread pool. The thread pool is then responsible for polling the future @@ -157,7 +168,7 @@ impl Handle { self.spawner.spawn(future) } - /// Run the provided function on an executor dedicated to blocking + /// Runs the provided function on an executor dedicated to blocking. /// operations. /// /// # Examples @@ -182,7 +193,11 @@ impl Handle { F: FnOnce() -> R + Send + 'static, R: Send + 'static, { - self.spawn_blocking_inner(func, None) + if cfg!(debug_assertions) && std::mem::size_of::<F>() > 2048 { + self.spawn_blocking_inner(Box::new(func), None) + } else { + self.spawn_blocking_inner(func, None) + } } #[cfg_attr(tokio_track_caller, track_caller)] @@ -226,7 +241,7 @@ impl Handle { handle } - /// Run a future to completion on this `Handle`'s associated `Runtime`. + /// Runs a future to completion on this `Handle`'s associated `Runtime`. /// /// This runs the given future on the current thread, blocking until it is /// complete, and yielding its resolved result. Any tasks or timers which @@ -319,17 +334,60 @@ impl Handle { } /// Error returned by `try_current` when no Runtime has been started -pub struct TryCurrentError(()); +#[derive(Debug)] +pub struct TryCurrentError { + kind: TryCurrentErrorKind, +} + +impl TryCurrentError { + pub(crate) fn new_no_context() -> Self { + Self { + kind: TryCurrentErrorKind::NoContext, + } + } + + pub(crate) fn new_thread_local_destroyed() -> Self { + Self { + kind: TryCurrentErrorKind::ThreadLocalDestroyed, + } + } -impl fmt::Debug for TryCurrentError { + /// Returns true if the call failed because there is currently no runtime in + /// the Tokio context. + pub fn is_missing_context(&self) -> bool { + matches!(self.kind, TryCurrentErrorKind::NoContext) + } + + /// Returns true if the call failed because the Tokio context thread-local + /// had been destroyed. This can usually only happen if in the destructor of + /// other thread-locals. + pub fn is_thread_local_destroyed(&self) -> bool { + matches!(self.kind, TryCurrentErrorKind::ThreadLocalDestroyed) + } +} + +enum TryCurrentErrorKind { + NoContext, + ThreadLocalDestroyed, +} + +impl fmt::Debug for TryCurrentErrorKind { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("TryCurrentError").finish() + use TryCurrentErrorKind::*; + match self { + NoContext => f.write_str("NoContext"), + ThreadLocalDestroyed => f.write_str("ThreadLocalDestroyed"), + } } } impl fmt::Display for TryCurrentError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str(CONTEXT_MISSING_ERROR) + use TryCurrentErrorKind::*; + match self.kind { + NoContext => f.write_str(CONTEXT_MISSING_ERROR), + ThreadLocalDestroyed => f.write_str(THREAD_LOCAL_DESTROYED_ERROR), + } } } |