aboutsummaryrefslogtreecommitdiff
path: root/src/runtime/handle.rs
diff options
context:
space:
mode:
authorJeff Vander Stoep <jeffv@google.com>2021-11-16 11:16:30 +0100
committerJeff Vander Stoep <jeffv@google.com>2021-11-16 11:17:30 +0100
commit1db412d2c35d13b9d4b8ab28ca56de5b77abff71 (patch)
treea86a1094890ceb522b599e1f37f24c2e16239fd3 /src/runtime/handle.rs
parente16ac718df3b8af3bef9bc0c1b6c9bfb5f8e71e1 (diff)
downloadtokio-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.rs92
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),
+ }
}
}