diff options
Diffstat (limited to 'vendor/tokio/src/macros')
-rw-r--r-- | vendor/tokio/src/macros/addr_of.rs | 22 | ||||
-rw-r--r-- | vendor/tokio/src/macros/cfg.rs | 227 | ||||
-rw-r--r-- | vendor/tokio/src/macros/join.rs | 75 | ||||
-rw-r--r-- | vendor/tokio/src/macros/loom.rs | 6 | ||||
-rw-r--r-- | vendor/tokio/src/macros/mod.rs | 8 | ||||
-rw-r--r-- | vendor/tokio/src/macros/scoped_tls.rs | 77 | ||||
-rw-r--r-- | vendor/tokio/src/macros/select.rs | 44 | ||||
-rw-r--r-- | vendor/tokio/src/macros/support.rs | 6 | ||||
-rw-r--r-- | vendor/tokio/src/macros/thread_local.rs | 30 | ||||
-rw-r--r-- | vendor/tokio/src/macros/trace.rs | 26 | ||||
-rw-r--r-- | vendor/tokio/src/macros/try_join.rs | 120 |
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 } } |