diff --git a/tokio/Cargo.toml b/tokio/Cargo.toml index c9d2e4e6d82..9228b3c6449 100644 --- a/tokio/Cargo.toml +++ b/tokio/Cargo.toml @@ -100,6 +100,9 @@ time = [] # a few releases. stats = [] +[build-dependencies] +autocfg = "1.1" + [dependencies] tokio-macros = { version = "1.7.0", path = "../tokio-macros", optional = true } diff --git a/tokio/build.rs b/tokio/build.rs new file mode 100644 index 00000000000..4c04a84d050 --- /dev/null +++ b/tokio/build.rs @@ -0,0 +1,22 @@ +use autocfg::AutoCfg; + +fn main() { + match AutoCfg::new() { + Ok(ac) => { + // Const-initialized thread locals were stabilized in 1.59 + if ac.probe_rustc_version(1, 59) { + autocfg::emit("tokio_const_thread_local") + } + } + + Err(e) => { + // If we couldn't detect the compiler version and features, just + // print a warning. This isn't a fatal error: we can still build + // Tokio, we just can't enable cfgs automatically. + println!( + "cargo:warning=tokio: failed to detect compiler features: {}", + e + ); + } + } +} diff --git a/tokio/src/coop.rs b/tokio/src/coop.rs index 96905319b65..bde1888a367 100644 --- a/tokio/src/coop.rs +++ b/tokio/src/coop.rs @@ -32,7 +32,7 @@ use std::cell::Cell; thread_local! { - static CURRENT: Cell = Cell::new(Budget::unconstrained()); + static CURRENT: Cell = const { Cell::new(Budget::unconstrained()) }; } /// Opaque type tracking the amount of "work" a task may still do before diff --git a/tokio/src/macros/scoped_tls.rs b/tokio/src/macros/scoped_tls.rs index f2504cbadf7..2ff90c06d79 100644 --- a/tokio/src/macros/scoped_tls.rs +++ b/tokio/src/macros/scoped_tls.rs @@ -10,7 +10,7 @@ macro_rules! scoped_thread_local { $vis static $name: $crate::macros::scoped_tls::ScopedKey<$ty> = $crate::macros::scoped_tls::ScopedKey { inner: { - thread_local!(static FOO: ::std::cell::Cell<*const ()> = { + thread_local!(static FOO: ::std::cell::Cell<*const ()> = const { std::cell::Cell::new(::std::ptr::null()) }); &FOO diff --git a/tokio/src/macros/thread_local.rs b/tokio/src/macros/thread_local.rs index d848947350d..e82a3307249 100644 --- a/tokio/src/macros/thread_local.rs +++ b/tokio/src/macros/thread_local.rs @@ -1,4 +1,28 @@ #[cfg(all(loom, test))] macro_rules! 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(all(tokio_const_thread_local, not(all(loom, test))))] +macro_rules! thread_local { + ($($tts:tt)+) => { ::std::thread_local!{ $($tts)+ } } +} + +#[cfg(all(not(tokio_const_thread_local), not(all(loom, test))))] +macro_rules! 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/tokio/src/runtime/context.rs b/tokio/src/runtime/context.rs index c31caf203ac..36fa28db356 100644 --- a/tokio/src/runtime/context.rs +++ b/tokio/src/runtime/context.rs @@ -4,7 +4,7 @@ use crate::runtime::{Handle, TryCurrentError}; use std::cell::RefCell; thread_local! { - static CONTEXT: RefCell> = RefCell::new(None) + static CONTEXT: RefCell> = const { RefCell::new(None) } } pub(crate) fn try_current() -> Result { diff --git a/tokio/src/runtime/enter.rs b/tokio/src/runtime/enter.rs index 3f14cb58782..7d2c7773832 100644 --- a/tokio/src/runtime/enter.rs +++ b/tokio/src/runtime/enter.rs @@ -17,7 +17,7 @@ impl EnterContext { } } -thread_local!(static ENTERED: Cell = Cell::new(EnterContext::NotEntered)); +thread_local!(static ENTERED: Cell = const { Cell::new(EnterContext::NotEntered) }); /// Represents an executor context. pub(crate) struct Enter { diff --git a/tokio/src/task/task_local.rs b/tokio/src/task/task_local.rs index 949bbca3eee..70fa967df5e 100644 --- a/tokio/src/task/task_local.rs +++ b/tokio/src/task/task_local.rs @@ -48,6 +48,22 @@ macro_rules! task_local { } #[doc(hidden)] +#[cfg(tokio_const_thread_local)] +#[macro_export] +macro_rules! __task_local_inner { + ($(#[$attr:meta])* $vis:vis $name:ident, $t:ty) => { + $vis static $name: $crate::task::LocalKey<$t> = { + std::thread_local! { + static __KEY: std::cell::RefCell> = const { std::cell::RefCell::new(None) }; + } + + $crate::task::LocalKey { inner: __KEY } + }; + }; +} + +#[doc(hidden)] +#[cfg(not(tokio_const_thread_local))] #[macro_export] macro_rules! __task_local_inner { ($(#[$attr:meta])* $vis:vis $name:ident, $t:ty) => {