summaryrefslogtreecommitdiffstats
path: root/vendor/tokio/src/macros
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/tokio/src/macros')
-rw-r--r--vendor/tokio/src/macros/addr_of.rs22
-rw-r--r--vendor/tokio/src/macros/cfg.rs227
-rw-r--r--vendor/tokio/src/macros/join.rs75
-rw-r--r--vendor/tokio/src/macros/loom.rs6
-rw-r--r--vendor/tokio/src/macros/mod.rs8
-rw-r--r--vendor/tokio/src/macros/scoped_tls.rs77
-rw-r--r--vendor/tokio/src/macros/select.rs44
-rw-r--r--vendor/tokio/src/macros/support.rs6
-rw-r--r--vendor/tokio/src/macros/thread_local.rs30
-rw-r--r--vendor/tokio/src/macros/trace.rs26
-rw-r--r--vendor/tokio/src/macros/try_join.rs120
11 files changed, 501 insertions, 140 deletions
diff --git a/vendor/tokio/src/macros/addr_of.rs b/vendor/tokio/src/macros/addr_of.rs
new file mode 100644
index 000000000..9d28158f2
--- /dev/null
+++ b/vendor/tokio/src/macros/addr_of.rs
@@ -0,0 +1,22 @@
+//! This module defines a macro that lets you go from a raw pointer to a struct
+//! to a raw pointer to a field of the struct.
+
+macro_rules! generate_addr_of_methods {
+ (
+ impl<$($gen:ident)*> $struct_name:ty {$(
+ $(#[$attrs:meta])*
+ $vis:vis unsafe fn $fn_name:ident(self: NonNull<Self>) -> NonNull<$field_type:ty> {
+ &self$(.$field_name:tt)+
+ }
+ )*}
+ ) => {
+ impl<$($gen)*> $struct_name {$(
+ $(#[$attrs])*
+ $vis unsafe fn $fn_name(me: ::core::ptr::NonNull<Self>) -> ::core::ptr::NonNull<$field_type> {
+ let me = me.as_ptr();
+ let field = ::std::ptr::addr_of_mut!((*me) $(.$field_name)+ );
+ ::core::ptr::NonNull::new_unchecked(field)
+ }
+ )*}
+ };
+}
diff --git a/vendor/tokio/src/macros/cfg.rs b/vendor/tokio/src/macros/cfg.rs
index 1e77556d8..52ffc102b 100644
--- a/vendor/tokio/src/macros/cfg.rs
+++ b/vendor/tokio/src/macros/cfg.rs
@@ -13,7 +13,19 @@ macro_rules! feature {
}
}
-/// Enables enter::block_on
+/// Enables Windows-specific code.
+/// Use this macro instead of `cfg(windows)` to generate docs properly.
+macro_rules! cfg_windows {
+ ($($item:item)*) => {
+ $(
+ #[cfg(any(all(doc, docsrs), windows))]
+ #[cfg_attr(docsrs, doc(cfg(windows)))]
+ $item
+ )*
+ }
+}
+
+/// Enables enter::block_on.
macro_rules! cfg_block_on {
($($item:item)*) => {
$(
@@ -28,7 +40,7 @@ macro_rules! cfg_block_on {
}
}
-/// Enables internal `AtomicWaker` impl
+/// Enables internal `AtomicWaker` impl.
macro_rules! cfg_atomic_waker_impl {
($($item:item)*) => {
$(
@@ -45,10 +57,23 @@ macro_rules! cfg_atomic_waker_impl {
}
}
+macro_rules! cfg_aio {
+ ($($item:item)*) => {
+ $(
+ #[cfg(all(any(docsrs, target_os = "freebsd"), feature = "net"))]
+ #[cfg_attr(docsrs,
+ doc(cfg(all(target_os = "freebsd", feature = "net")))
+ )]
+ $item
+ )*
+ }
+}
+
macro_rules! cfg_fs {
($($item:item)*) => {
$(
#[cfg(feature = "fs")]
+ #[cfg(not(tokio_wasi))]
#[cfg_attr(docsrs, doc(cfg(feature = "fs")))]
$item
)*
@@ -57,7 +82,11 @@ macro_rules! cfg_fs {
macro_rules! cfg_io_blocking {
($($item:item)*) => {
- $( #[cfg(any(feature = "io-std", feature = "fs"))] $item )*
+ $( #[cfg(any(
+ feature = "io-std",
+ feature = "fs",
+ all(windows, feature = "process"),
+ ))] $item )*
}
}
@@ -66,12 +95,12 @@ macro_rules! cfg_io_driver {
$(
#[cfg(any(
feature = "net",
- feature = "process",
+ all(unix, feature = "process"),
all(unix, feature = "signal"),
))]
#[cfg_attr(docsrs, doc(cfg(any(
feature = "net",
- feature = "process",
+ all(unix, feature = "process"),
all(unix, feature = "signal"),
))))]
$item
@@ -84,7 +113,7 @@ macro_rules! cfg_io_driver_impl {
$(
#[cfg(any(
feature = "net",
- feature = "process",
+ all(unix, feature = "process"),
all(unix, feature = "signal"),
))]
$item
@@ -97,7 +126,7 @@ macro_rules! cfg_not_io_driver {
$(
#[cfg(not(any(
feature = "net",
- feature = "process",
+ all(unix, feature = "process"),
all(unix, feature = "signal"),
)))]
$item
@@ -162,6 +191,43 @@ macro_rules! cfg_macros {
}
}
+macro_rules! cfg_metrics {
+ ($($item:item)*) => {
+ $(
+ // For now, metrics is only disabled in loom tests.
+ // When stabilized, it might have a dedicated feature flag.
+ #[cfg(all(tokio_unstable, not(loom)))]
+ #[cfg_attr(docsrs, doc(cfg(tokio_unstable)))]
+ $item
+ )*
+ }
+}
+
+macro_rules! cfg_not_metrics {
+ ($($item:item)*) => {
+ $(
+ #[cfg(not(all(tokio_unstable, not(loom))))]
+ $item
+ )*
+ }
+}
+
+macro_rules! cfg_not_rt_and_metrics_and_net {
+ ($($item:item)*) => {
+ $( #[cfg(not(all(feature = "net", feature = "rt", all(tokio_unstable, not(loom)))))]$item )*
+ }
+}
+
+macro_rules! cfg_net_or_process {
+ ($($item:item)*) => {
+ $(
+ #[cfg(any(feature = "net", feature = "process"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "net", feature = "process"))))]
+ $item
+ )*
+ }
+}
+
macro_rules! cfg_net {
($($item:item)*) => {
$(
@@ -176,7 +242,7 @@ macro_rules! cfg_net_unix {
($($item:item)*) => {
$(
#[cfg(all(unix, feature = "net"))]
- #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
+ #[cfg_attr(docsrs, doc(cfg(all(unix, feature = "net"))))]
$item
)*
}
@@ -185,7 +251,7 @@ macro_rules! cfg_net_unix {
macro_rules! cfg_net_windows {
($($item:item)*) => {
$(
- #[cfg(all(any(docsrs, windows), feature = "net"))]
+ #[cfg(all(any(all(doc, docsrs), windows), feature = "net"))]
#[cfg_attr(docsrs, doc(cfg(all(windows, feature = "net"))))]
$item
)*
@@ -198,6 +264,7 @@ macro_rules! cfg_process {
#[cfg(feature = "process")]
#[cfg_attr(docsrs, doc(cfg(feature = "process")))]
#[cfg(not(loom))]
+ #[cfg(not(tokio_wasi))]
$item
)*
}
@@ -226,6 +293,7 @@ macro_rules! cfg_signal {
#[cfg(feature = "signal")]
#[cfg_attr(docsrs, doc(cfg(feature = "signal")))]
#[cfg(not(loom))]
+ #[cfg(not(tokio_wasi))]
$item
)*
}
@@ -241,6 +309,13 @@ macro_rules! cfg_signal_internal {
}
}
+macro_rules! cfg_signal_internal_and_unix {
+ ($($item:item)*) => {
+ #[cfg(unix)]
+ cfg_signal_internal! { $($item)* }
+ }
+}
+
macro_rules! cfg_not_signal_internal {
($($item:item)*) => {
$(
@@ -285,7 +360,7 @@ macro_rules! cfg_not_rt {
macro_rules! cfg_rt_multi_thread {
($($item:item)*) => {
$(
- #[cfg(feature = "rt-multi-thread")]
+ #[cfg(all(feature = "rt-multi-thread", not(tokio_wasi)))]
#[cfg_attr(docsrs, doc(cfg(feature = "rt-multi-thread")))]
$item
)*
@@ -298,6 +373,44 @@ macro_rules! cfg_not_rt_multi_thread {
}
}
+macro_rules! cfg_taskdump {
+ ($($item:item)*) => {
+ $(
+ #[cfg(all(
+ tokio_unstable,
+ tokio_taskdump,
+ feature = "rt",
+ target_os = "linux",
+ any(
+ target_arch = "aarch64",
+ target_arch = "x86",
+ target_arch = "x86_64"
+ )
+ ))]
+ $item
+ )*
+ };
+}
+
+macro_rules! cfg_not_taskdump {
+ ($($item:item)*) => {
+ $(
+ #[cfg(not(all(
+ tokio_unstable,
+ tokio_taskdump,
+ feature = "rt",
+ target_os = "linux",
+ any(
+ target_arch = "aarch64",
+ target_arch = "x86",
+ target_arch = "x86_64"
+ )
+ )))]
+ $item
+ )*
+ };
+}
+
macro_rules! cfg_test_util {
($($item:item)*) => {
$(
@@ -334,10 +447,20 @@ macro_rules! cfg_trace {
($($item:item)*) => {
$(
#[cfg(all(tokio_unstable, feature = "tracing"))]
- #[cfg_attr(docsrs, doc(cfg(feature = "tracing")))]
+ #[cfg_attr(docsrs, doc(cfg(all(tokio_unstable, feature = "tracing"))))]
$item
)*
- }
+ };
+}
+
+macro_rules! cfg_unstable {
+ ($($item:item)*) => {
+ $(
+ #[cfg(tokio_unstable)]
+ #[cfg_attr(docsrs, doc(cfg(tokio_unstable)))]
+ $item
+ )*
+ };
}
macro_rules! cfg_not_trace {
@@ -384,3 +507,83 @@ macro_rules! cfg_not_coop {
)*
}
}
+
+macro_rules! cfg_has_atomic_u64 {
+ ($($item:item)*) => {
+ $(
+ #[cfg_attr(
+ not(tokio_no_target_has_atomic),
+ cfg(all(target_has_atomic = "64", not(tokio_no_atomic_u64))
+ ))]
+ #[cfg_attr(
+ tokio_no_target_has_atomic,
+ cfg(not(tokio_no_atomic_u64))
+ )]
+ $item
+ )*
+ }
+}
+
+macro_rules! cfg_not_has_atomic_u64 {
+ ($($item:item)*) => {
+ $(
+ #[cfg_attr(
+ not(tokio_no_target_has_atomic),
+ cfg(any(not(target_has_atomic = "64"), tokio_no_atomic_u64)
+ ))]
+ #[cfg_attr(
+ tokio_no_target_has_atomic,
+ cfg(tokio_no_atomic_u64)
+ )]
+ $item
+ )*
+ }
+}
+
+macro_rules! cfg_has_const_mutex_new {
+ ($($item:item)*) => {
+ $(
+ #[cfg(all(
+ not(all(loom, test)),
+ any(
+ feature = "parking_lot",
+ not(tokio_no_const_mutex_new)
+ )
+ ))]
+ $item
+ )*
+ }
+}
+
+macro_rules! cfg_not_has_const_mutex_new {
+ ($($item:item)*) => {
+ $(
+ #[cfg(not(all(
+ not(all(loom, test)),
+ any(
+ feature = "parking_lot",
+ not(tokio_no_const_mutex_new)
+ )
+ )))]
+ $item
+ )*
+ }
+}
+
+macro_rules! cfg_not_wasi {
+ ($($item:item)*) => {
+ $(
+ #[cfg(not(tokio_wasi))]
+ $item
+ )*
+ }
+}
+
+macro_rules! cfg_is_wasm_not_wasi {
+ ($($item:item)*) => {
+ $(
+ #[cfg(tokio_wasm_not_wasi)]
+ $item
+ )*
+ }
+}
diff --git a/vendor/tokio/src/macros/join.rs b/vendor/tokio/src/macros/join.rs
index 5f37af510..8a0198600 100644
--- a/vendor/tokio/src/macros/join.rs
+++ b/vendor/tokio/src/macros/join.rs
@@ -1,4 +1,4 @@
-/// Wait on multiple concurrent branches, returning when **all** branches
+/// Waits on multiple concurrent branches, returning when **all** branches
/// complete.
///
/// The `join!` macro must be used inside of async functions, closures, and
@@ -12,7 +12,7 @@
/// for **all** branches complete regardless if any complete with `Err`. Use
/// [`try_join!`] to return early when `Err` is encountered.
///
-/// [`try_join!`]: macro@try_join
+/// [`try_join!`]: crate::try_join
///
/// # Notes
///
@@ -60,6 +60,9 @@ macro_rules! join {
// normalization is complete.
( $($count:tt)* )
+ // The expression `0+1+1+ ... +1` equal to the number of branches.
+ ( $($total:tt)* )
+
// Normalized join! branches
$( ( $($skip:tt)* ) $e:expr, )*
@@ -69,24 +72,66 @@ macro_rules! join {
// Safety: nothing must be moved out of `futures`. This is to satisfy
// the requirement of `Pin::new_unchecked` called below.
+ //
+ // We can't use the `pin!` macro for this because `futures` is a tuple
+ // and the standard library provides no way to pin-project to the fields
+ // of a tuple.
let mut futures = ( $( maybe_done($e), )* );
+ // This assignment makes sure that the `poll_fn` closure only has a
+ // reference to the futures, instead of taking ownership of them. This
+ // mitigates the issue described in
+ // <https://internals.rust-lang.org/t/surprising-soundness-trouble-around-pollfn/17484>
+ let mut futures = &mut futures;
+
+ // Each time the future created by poll_fn is polled, a different future will be polled first
+ // to ensure every future passed to join! gets a chance to make progress even if
+ // one of the futures consumes the whole budget.
+ //
+ // This is number of futures that will be skipped in the first loop
+ // iteration the next time.
+ let mut skip_next_time: u32 = 0;
+
poll_fn(move |cx| {
+ const COUNT: u32 = $($total)*;
+
let mut is_pending = false;
+ let mut to_run = COUNT;
+
+ // The number of futures that will be skipped in the first loop iteration.
+ let mut skip = skip_next_time;
+
+ skip_next_time = if skip + 1 == COUNT { 0 } else { skip + 1 };
+
+ // This loop runs twice and the first `skip` futures
+ // are not polled in the first iteration.
+ loop {
$(
- // Extract the future for this branch from the tuple.
- let ( $($skip,)* fut, .. ) = &mut futures;
+ if skip == 0 {
+ if to_run == 0 {
+ // Every future has been polled
+ break;
+ }
+ to_run -= 1;
- // Safety: future is stored on the stack above
- // and never moved.
- let mut fut = unsafe { Pin::new_unchecked(fut) };
+ // Extract the future for this branch from the tuple.
+ let ( $($skip,)* fut, .. ) = &mut *futures;
- // Try polling
- if fut.poll(cx).is_pending() {
- is_pending = true;
+ // Safety: future is stored on the stack above
+ // and never moved.
+ let mut fut = unsafe { Pin::new_unchecked(fut) };
+
+ // Try polling
+ if fut.poll(cx).is_pending() {
+ is_pending = true;
+ }
+ } else {
+ // Future skipped, one less future to skip in the next iteration
+ skip -= 1;
}
)*
+ }
if is_pending {
Pending
@@ -107,13 +152,15 @@ macro_rules! join {
// ===== Normalize =====
- (@ { ( $($s:tt)* ) $($t:tt)* } $e:expr, $($r:tt)* ) => {
- $crate::join!(@{ ($($s)* _) $($t)* ($($s)*) $e, } $($r)*)
+ (@ { ( $($s:tt)* ) ( $($n:tt)* ) $($t:tt)* } $e:expr, $($r:tt)* ) => {
+ $crate::join!(@{ ($($s)* _) ($($n)* + 1) $($t)* ($($s)*) $e, } $($r)*)
};
// ===== Entry point =====
- ( $($e:expr),* $(,)?) => {
- $crate::join!(@{ () } $($e,)*)
+ ( $($e:expr),+ $(,)?) => {
+ $crate::join!(@{ () (0) } $($e,)*)
};
+
+ () => { async {}.await }
}
diff --git a/vendor/tokio/src/macros/loom.rs b/vendor/tokio/src/macros/loom.rs
index d57d9fb0f..fa2653ce7 100644
--- a/vendor/tokio/src/macros/loom.rs
+++ b/vendor/tokio/src/macros/loom.rs
@@ -1,11 +1,7 @@
macro_rules! if_loom {
($($t:tt)*) => {{
#[cfg(loom)]
- const LOOM: bool = true;
- #[cfg(not(loom))]
- const LOOM: bool = false;
-
- if LOOM {
+ {
$($t)*
}
}}
diff --git a/vendor/tokio/src/macros/mod.rs b/vendor/tokio/src/macros/mod.rs
index b0af52152..82f42dbff 100644
--- a/vendor/tokio/src/macros/mod.rs
+++ b/vendor/tokio/src/macros/mod.rs
@@ -16,8 +16,12 @@ mod ready;
mod thread_local;
#[macro_use]
-#[cfg(feature = "rt")]
-pub(crate) mod scoped_tls;
+mod addr_of;
+
+cfg_trace! {
+ #[macro_use]
+ mod trace;
+}
cfg_macros! {
#[macro_use]
diff --git a/vendor/tokio/src/macros/scoped_tls.rs b/vendor/tokio/src/macros/scoped_tls.rs
deleted file mode 100644
index a00aae2fb..000000000
--- a/vendor/tokio/src/macros/scoped_tls.rs
+++ /dev/null
@@ -1,77 +0,0 @@
-use crate::loom::thread::LocalKey;
-
-use std::cell::Cell;
-use std::marker;
-
-/// Set a reference as a thread-local
-macro_rules! scoped_thread_local {
- ($(#[$attrs:meta])* $vis:vis static $name:ident: $ty:ty) => (
- $(#[$attrs])*
- $vis static $name: $crate::macros::scoped_tls::ScopedKey<$ty>
- = $crate::macros::scoped_tls::ScopedKey {
- inner: {
- thread_local!(static FOO: ::std::cell::Cell<*const ()> = {
- std::cell::Cell::new(::std::ptr::null())
- });
- &FOO
- },
- _marker: ::std::marker::PhantomData,
- };
- )
-}
-
-/// Type representing a thread local storage key corresponding to a reference
-/// to the type parameter `T`.
-pub(crate) struct ScopedKey<T> {
- pub(crate) inner: &'static LocalKey<Cell<*const ()>>,
- pub(crate) _marker: marker::PhantomData<T>,
-}
-
-unsafe impl<T> Sync for ScopedKey<T> {}
-
-impl<T> ScopedKey<T> {
- /// Inserts a value into this scoped thread local storage slot for a
- /// duration of a closure.
- pub(crate) fn set<F, R>(&'static self, t: &T, f: F) -> R
- where
- F: FnOnce() -> R,
- {
- struct Reset {
- key: &'static LocalKey<Cell<*const ()>>,
- val: *const (),
- }
-
- impl Drop for Reset {
- fn drop(&mut self) {
- self.key.with(|c| c.set(self.val));
- }
- }
-
- let prev = self.inner.with(|c| {
- let prev = c.get();
- c.set(t as *const _ as *const ());
- prev
- });
-
- let _reset = Reset {
- key: self.inner,
- val: prev,
- };
-
- f()
- }
-
- /// Gets a value out of this scoped variable.
- pub(crate) fn with<F, R>(&'static self, f: F) -> R
- where
- F: FnOnce(Option<&T>) -> R,
- {
- let val = self.inner.with(|c| c.get());
-
- if val.is_null() {
- f(None)
- } else {
- unsafe { f(Some(&*(val as *const T))) }
- }
- }
-}
diff --git a/vendor/tokio/src/macros/select.rs b/vendor/tokio/src/macros/select.rs
index a90ee9eb5..31c9b3ac2 100644
--- a/vendor/tokio/src/macros/select.rs
+++ b/vendor/tokio/src/macros/select.rs
@@ -1,4 +1,4 @@
-/// Wait on multiple concurrent branches, returning when the **first** branch
+/// Waits on multiple concurrent branches, returning when the **first** branch
/// completes, cancelling the remaining branches.
///
/// The `select!` macro must be used inside of async functions, closures, and
@@ -101,6 +101,7 @@
/// * [`tokio::sync::watch::Receiver::changed`](crate::sync::watch::Receiver::changed)
/// * [`tokio::net::TcpListener::accept`](crate::net::TcpListener::accept)
/// * [`tokio::net::UnixListener::accept`](crate::net::UnixListener::accept)
+/// * [`tokio::signal::unix::Signal::recv`](crate::signal::unix::Signal::recv)
/// * [`tokio::io::AsyncReadExt::read`](crate::io::AsyncReadExt::read) on any `AsyncRead`
/// * [`tokio::io::AsyncReadExt::read_buf`](crate::io::AsyncReadExt::read_buf) on any `AsyncRead`
/// * [`tokio::io::AsyncWriteExt::write`](crate::io::AsyncWriteExt::write) on any `AsyncWrite`
@@ -130,6 +131,13 @@
/// correctly even if it is restarted while waiting at an `.await`, then it is
/// cancellation safe.
///
+/// Cancellation safety can be defined in the following way: If you have a
+/// future that has not yet completed, then it must be a no-op to drop that
+/// future and recreate it. This definition is motivated by the situation where
+/// a `select!` is used in a loop. Without this guarantee, you would lose your
+/// progress when another branch completes and you restart the `select!` by
+/// going around the loop.
+///
/// Be aware that cancelling something that is not cancellation safe is not
/// necessarily wrong. For example, if you are cancelling a task because the
/// application is shutting down, then you probably don't care that partially
@@ -429,7 +437,8 @@ macro_rules! select {
//
// This module is defined within a scope and should not leak out of this
// macro.
- mod util {
+ #[doc(hidden)]
+ mod __tokio_select_util {
// Generate an enum with one variant per select branch
$crate::select_priv_declare_output_enum!( ( $($count)* ) );
}
@@ -442,13 +451,13 @@ macro_rules! select {
const BRANCHES: u32 = $crate::count!( $($count)* );
- let mut disabled: util::Mask = Default::default();
+ let mut disabled: __tokio_select_util::Mask = Default::default();
// First, invoke all the pre-conditions. For any that return true,
// set the appropriate bit in `disabled`.
$(
if !$c {
- let mask: util::Mask = 1 << $crate::count!( $($skip)* );
+ let mask: __tokio_select_util::Mask = 1 << $crate::count!( $($skip)* );
disabled |= mask;
}
)*
@@ -458,8 +467,18 @@ macro_rules! select {
let mut output = {
// Safety: Nothing must be moved out of `futures`. This is to
// satisfy the requirement of `Pin::new_unchecked` called below.
+ //
+ // We can't use the `pin!` macro for this because `futures` is a
+ // tuple and the standard library provides no way to pin-project to
+ // the fields of a tuple.
let mut futures = ( $( $fut , )+ );
+ // This assignment makes sure that the `poll_fn` closure only has a
+ // reference to the futures, instead of taking ownership of them.
+ // This mitigates the issue described in
+ // <https://internals.rust-lang.org/t/surprising-soundness-trouble-around-pollfn/17484>
+ let mut futures = &mut futures;
+
$crate::macros::support::poll_fn(|cx| {
// Track if any branch returns pending. If no branch completes
// **or** returns pending, this implies that all branches are
@@ -495,14 +514,14 @@ macro_rules! select {
// Extract the future for this branch from the
// tuple
- let ( $($skip,)* fut, .. ) = &mut futures;
+ let ( $($skip,)* fut, .. ) = &mut *futures;
// Safety: future is stored on the stack above
// and never moved.
let mut fut = unsafe { Pin::new_unchecked(fut) };
// Try polling it
- let out = match fut.poll(cx) {
+ let out = match Future::poll(fut, cx) {
Ready(out) => out,
Pending => {
// Track that at least one future is
@@ -520,12 +539,12 @@ macro_rules! select {
#[allow(unused_variables)]
#[allow(unused_mut)]
match &out {
- $bind => {}
+ $crate::select_priv_clean_pattern!($bind) => {}
_ => continue,
}
// The select is complete, return the value
- return Ready($crate::select_variant!(util::Out, ($($skip)*))(out));
+ return Ready($crate::select_variant!(__tokio_select_util::Out, ($($skip)*))(out));
}
)*
_ => unreachable!("reaching this means there probably is an off by one bug"),
@@ -536,16 +555,16 @@ macro_rules! select {
Pending
} else {
// All branches have been disabled.
- Ready(util::Out::Disabled)
+ Ready(__tokio_select_util::Out::Disabled)
}
}).await
};
match output {
$(
- $crate::select_variant!(util::Out, ($($skip)*) ($bind)) => $handle,
+ $crate::select_variant!(__tokio_select_util::Out, ($($skip)*) ($bind)) => $handle,
)*
- util::Out::Disabled => $else,
+ __tokio_select_util::Out::Disabled => $else,
_ => unreachable!("failed to match bind"),
}
}};
@@ -801,6 +820,9 @@ macro_rules! count {
(_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _) => {
63
};
+ (_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _) => {
+ 64
+ };
}
#[macro_export]
diff --git a/vendor/tokio/src/macros/support.rs b/vendor/tokio/src/macros/support.rs
index 7f11bc680..10526bcbc 100644
--- a/vendor/tokio/src/macros/support.rs
+++ b/vendor/tokio/src/macros/support.rs
@@ -1,7 +1,11 @@
cfg_macros! {
pub use crate::future::poll_fn;
pub use crate::future::maybe_done::maybe_done;
- pub use crate::util::thread_rng_n;
+
+ #[doc(hidden)]
+ pub fn thread_rng_n(n: u32) -> u32 {
+ crate::runtime::context::thread_rng_n(n)
+ }
}
pub use std::future::Future;
diff --git a/vendor/tokio/src/macros/thread_local.rs b/vendor/tokio/src/macros/thread_local.rs
index d84894735..74be99abf 100644
--- a/vendor/tokio/src/macros/thread_local.rs
+++ b/vendor/tokio/src/macros/thread_local.rs
@@ -1,4 +1,32 @@
#[cfg(all(loom, test))]
-macro_rules! thread_local {
+macro_rules! tokio_thread_local {
+ ($(#[$attrs:meta])* $vis:vis static $name:ident: $ty:ty = const { $expr:expr } $(;)?) => {
+ loom::thread_local! {
+ $(#[$attrs])*
+ $vis static $name: $ty = $expr;
+ }
+ };
+
($($tts:tt)+) => { loom::thread_local!{ $($tts)+ } }
}
+
+#[cfg(not(tokio_no_const_thread_local))]
+#[cfg(not(all(loom, test)))]
+macro_rules! tokio_thread_local {
+ ($($tts:tt)+) => {
+ ::std::thread_local!{ $($tts)+ }
+ }
+}
+
+#[cfg(tokio_no_const_thread_local)]
+#[cfg(not(all(loom, test)))]
+macro_rules! tokio_thread_local {
+ ($(#[$attrs:meta])* $vis:vis static $name:ident: $ty:ty = const { $expr:expr } $(;)?) => {
+ ::std::thread_local! {
+ $(#[$attrs])*
+ $vis static $name: $ty = $expr;
+ }
+ };
+
+ ($($tts:tt)+) => { ::std::thread_local!{ $($tts)+ } }
+}
diff --git a/vendor/tokio/src/macros/trace.rs b/vendor/tokio/src/macros/trace.rs
new file mode 100644
index 000000000..80a257e18
--- /dev/null
+++ b/vendor/tokio/src/macros/trace.rs
@@ -0,0 +1,26 @@
+cfg_trace! {
+ macro_rules! trace_op {
+ ($name:expr, $readiness:literal) => {
+ tracing::trace!(
+ target: "runtime::resource::poll_op",
+ op_name = $name,
+ is_ready = $readiness
+ );
+ }
+ }
+
+ macro_rules! trace_poll_op {
+ ($name:expr, $poll:expr $(,)*) => {
+ match $poll {
+ std::task::Poll::Ready(t) => {
+ trace_op!($name, true);
+ std::task::Poll::Ready(t)
+ }
+ std::task::Poll::Pending => {
+ trace_op!($name, false);
+ return std::task::Poll::Pending;
+ }
+ }
+ };
+ }
+}
diff --git a/vendor/tokio/src/macros/try_join.rs b/vendor/tokio/src/macros/try_join.rs
index fa5850ef0..7b1237092 100644
--- a/vendor/tokio/src/macros/try_join.rs
+++ b/vendor/tokio/src/macros/try_join.rs
@@ -1,4 +1,4 @@
-/// Wait on multiple concurrent branches, returning when **all** branches
+/// Waits on multiple concurrent branches, returning when **all** branches
/// complete with `Ok(_)` or on the first `Err(_)`.
///
/// The `try_join!` macro must be used inside of async functions, closures, and
@@ -59,6 +59,45 @@
/// }
/// }
/// ```
+///
+/// Using `try_join!` with spawned tasks.
+///
+/// ```
+/// use tokio::task::JoinHandle;
+///
+/// async fn do_stuff_async() -> Result<(), &'static str> {
+/// // async work
+/// # Err("failed")
+/// }
+///
+/// async fn more_async_work() -> Result<(), &'static str> {
+/// // more here
+/// # Ok(())
+/// }
+///
+/// async fn flatten<T>(handle: JoinHandle<Result<T, &'static str>>) -> Result<T, &'static str> {
+/// match handle.await {
+/// Ok(Ok(result)) => Ok(result),
+/// Ok(Err(err)) => Err(err),
+/// Err(err) => Err("handling failed"),
+/// }
+/// }
+///
+/// #[tokio::main]
+/// async fn main() {
+/// let handle1 = tokio::spawn(do_stuff_async());
+/// let handle2 = tokio::spawn(more_async_work());
+/// match tokio::try_join!(flatten(handle1), flatten(handle2)) {
+/// Ok(val) => {
+/// // do something with the values
+/// }
+/// Err(err) => {
+/// println!("Failed with {}.", err);
+/// # assert_eq!(err, "failed");
+/// }
+/// }
+/// }
+/// ```
#[macro_export]
#[cfg_attr(docsrs, doc(cfg(feature = "macros")))]
macro_rules! try_join {
@@ -67,6 +106,9 @@ macro_rules! try_join {
// normalization is complete.
( $($count:tt)* )
+ // The expression `0+1+1+ ... +1` equal to the number of branches.
+ ( $($total:tt)* )
+
// Normalized try_join! branches
$( ( $($skip:tt)* ) $e:expr, )*
@@ -76,26 +118,68 @@ macro_rules! try_join {
// Safety: nothing must be moved out of `futures`. This is to satisfy
// the requirement of `Pin::new_unchecked` called below.
+ //
+ // We can't use the `pin!` macro for this because `futures` is a tuple
+ // and the standard library provides no way to pin-project to the fields
+ // of a tuple.
let mut futures = ( $( maybe_done($e), )* );
+ // This assignment makes sure that the `poll_fn` closure only has a
+ // reference to the futures, instead of taking ownership of them. This
+ // mitigates the issue described in
+ // <https://internals.rust-lang.org/t/surprising-soundness-trouble-around-pollfn/17484>
+ let mut futures = &mut futures;
+
+ // Each time the future created by poll_fn is polled, a different future will be polled first
+ // to ensure every future passed to join! gets a chance to make progress even if
+ // one of the futures consumes the whole budget.
+ //
+ // This is number of futures that will be skipped in the first loop
+ // iteration the next time.
+ let mut skip_next_time: u32 = 0;
+
poll_fn(move |cx| {
+ const COUNT: u32 = $($total)*;
+
let mut is_pending = false;
+ let mut to_run = COUNT;
+
+ // The number of futures that will be skipped in the first loop iteration
+ let mut skip = skip_next_time;
+
+ skip_next_time = if skip + 1 == COUNT { 0 } else { skip + 1 };
+
+ // This loop runs twice and the first `skip` futures
+ // are not polled in the first iteration.
+ loop {
$(
- // Extract the future for this branch from the tuple.
- let ( $($skip,)* fut, .. ) = &mut futures;
-
- // Safety: future is stored on the stack above
- // and never moved.
- let mut fut = unsafe { Pin::new_unchecked(fut) };
-
- // Try polling
- if fut.as_mut().poll(cx).is_pending() {
- is_pending = true;
- } else if fut.as_mut().output_mut().expect("expected completed future").is_err() {
- return Ready(Err(fut.take_output().expect("expected completed future").err().unwrap()))
+ if skip == 0 {
+ if to_run == 0 {
+ // Every future has been polled
+ break;
+ }
+ to_run -= 1;
+
+ // Extract the future for this branch from the tuple.
+ let ( $($skip,)* fut, .. ) = &mut *futures;
+
+ // Safety: future is stored on the stack above
+ // and never moved.
+ let mut fut = unsafe { Pin::new_unchecked(fut) };
+
+ // Try polling
+ if fut.as_mut().poll(cx).is_pending() {
+ is_pending = true;
+ } else if fut.as_mut().output_mut().expect("expected completed future").is_err() {
+ return Ready(Err(fut.take_output().expect("expected completed future").err().unwrap()))
+ }
+ } else {
+ // Future skipped, one less future to skip in the next iteration
+ skip -= 1;
}
)*
+ }
if is_pending {
Pending
@@ -120,13 +204,15 @@ macro_rules! try_join {
// ===== Normalize =====
- (@ { ( $($s:tt)* ) $($t:tt)* } $e:expr, $($r:tt)* ) => {
- $crate::try_join!(@{ ($($s)* _) $($t)* ($($s)*) $e, } $($r)*)
+ (@ { ( $($s:tt)* ) ( $($n:tt)* ) $($t:tt)* } $e:expr, $($r:tt)* ) => {
+ $crate::try_join!(@{ ($($s)* _) ($($n)* + 1) $($t)* ($($s)*) $e, } $($r)*)
};
// ===== Entry point =====
- ( $($e:expr),* $(,)?) => {
- $crate::try_join!(@{ () } $($e,)*)
+ ( $($e:expr),+ $(,)?) => {
+ $crate::try_join!(@{ () (0) } $($e,)*)
};
+
+ () => { async { Ok(()) }.await }
}