Skip to content

Commit

Permalink
tokio: use const Mutex::new for globals (#5061)
Browse files Browse the repository at this point in the history
  • Loading branch information
Darksonn committed Sep 28, 2022
1 parent 96fab05 commit f4e08ae
Show file tree
Hide file tree
Showing 8 changed files with 126 additions and 29 deletions.
31 changes: 31 additions & 0 deletions tokio/build.rs
Expand Up @@ -17,9 +17,17 @@ const ADDR_OF_PROBE: &str = r#"
}
"#;

const CONST_MUTEX_NEW_PROBE: &str = r#"
{
static MY_MUTEX: ::std::sync::Mutex<i32> = ::std::sync::Mutex::new(1);
*MY_MUTEX.lock().unwrap()
}
"#;

fn main() {
let mut enable_const_thread_local = false;
let mut enable_addr_of = false;
let mut enable_const_mutex_new = false;

match AutoCfg::new() {
Ok(ac) => {
Expand Down Expand Up @@ -57,6 +65,21 @@ fn main() {
enable_addr_of = true;
}
}

// The `Mutex::new` method was made const in 1.63.
if ac.probe_rustc_version(1, 64) {
enable_const_mutex_new = true;
} else if ac.probe_rustc_version(1, 63) {
// This compiler claims to be 1.63, but there are some nightly
// compilers that claim to be 1.63 without supporting the
// feature. Explicitly probe to check if code using them
// compiles.
//
// The oldest nightly that supports the feature is 2022-06-20.
if ac.probe_expression(CONST_MUTEX_NEW_PROBE) {
enable_const_mutex_new = true;
}
}
}

Err(e) => {
Expand Down Expand Up @@ -86,6 +109,14 @@ fn main() {
autocfg::emit("tokio_no_addr_of")
}

if !enable_const_mutex_new {
// To disable this feature on compilers that support it, you can
// explicitly pass this flag with the following environment variable:
//
// RUSTFLAGS="--cfg tokio_no_const_mutex_new"
autocfg::emit("tokio_no_const_mutex_new")
}

let target = ::std::env::var("TARGET").unwrap_or_default();

// We emit cfgs instead of using `target_family = "wasm"` that requires Rust 1.54.
Expand Down
6 changes: 6 additions & 0 deletions tokio/src/loom/std/mutex.rs
Expand Up @@ -12,6 +12,12 @@ impl<T> Mutex<T> {
Mutex(sync::Mutex::new(t))
}

#[inline]
#[cfg(not(tokio_no_const_mutex_new))]
pub(crate) const fn const_new(t: T) -> Mutex<T> {
Mutex(sync::Mutex::new(t))
}

#[inline]
pub(crate) fn lock(&self) -> MutexGuard<'_, T> {
match self.0.lock() {
Expand Down
30 changes: 30 additions & 0 deletions tokio/src/macros/cfg.rs
Expand Up @@ -481,6 +481,36 @@ macro_rules! cfg_not_has_atomic_u64 {
}
}

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)*) => {
$(
Expand Down
19 changes: 15 additions & 4 deletions tokio/src/process/unix/mod.rs
Expand Up @@ -34,7 +34,6 @@ use crate::process::kill::Kill;
use crate::process::SpawnedChild;
use crate::signal::unix::driver::Handle as SignalHandle;
use crate::signal::unix::{signal, Signal, SignalKind};
use crate::util::once_cell::OnceCell;

use mio::event::Source;
use mio::unix::SourceFd;
Expand Down Expand Up @@ -64,10 +63,22 @@ impl Kill for StdChild {
}
}

fn get_orphan_queue() -> &'static OrphanQueueImpl<StdChild> {
static ORPHAN_QUEUE: OnceCell<OrphanQueueImpl<StdChild>> = OnceCell::new();
cfg_not_has_const_mutex_new! {
fn get_orphan_queue() -> &'static OrphanQueueImpl<StdChild> {
use crate::util::once_cell::OnceCell;

ORPHAN_QUEUE.get(OrphanQueueImpl::new)
static ORPHAN_QUEUE: OnceCell<OrphanQueueImpl<StdChild>> = OnceCell::new();

ORPHAN_QUEUE.get(OrphanQueueImpl::new)
}
}

cfg_has_const_mutex_new! {
fn get_orphan_queue() -> &'static OrphanQueueImpl<StdChild> {
static ORPHAN_QUEUE: OrphanQueueImpl<StdChild> = OrphanQueueImpl::new();

&ORPHAN_QUEUE
}
}

pub(crate) struct GlobalOrphanQueue;
Expand Down
19 changes: 15 additions & 4 deletions tokio/src/process/unix/orphan.rs
Expand Up @@ -43,10 +43,21 @@ pub(crate) struct OrphanQueueImpl<T> {
}

impl<T> OrphanQueueImpl<T> {
pub(crate) fn new() -> Self {
Self {
sigchild: Mutex::new(None),
queue: Mutex::new(Vec::new()),
cfg_not_has_const_mutex_new! {
pub(crate) fn new() -> Self {
Self {
sigchild: Mutex::new(None),
queue: Mutex::new(Vec::new()),
}
}
}

cfg_has_const_mutex_new! {
pub(crate) const fn new() -> Self {
Self {
sigchild: Mutex::const_new(None),
queue: Mutex::const_new(Vec::new()),
}
}
}

Expand Down
38 changes: 26 additions & 12 deletions tokio/src/runtime/task/mod.rs
Expand Up @@ -507,21 +507,35 @@ impl Id {
}

cfg_not_has_atomic_u64! {
pub(crate) fn next() -> Self {
use crate::util::once_cell::OnceCell;
use crate::loom::sync::Mutex;

fn init_next_id() -> Mutex<u64> {
Mutex::new(1)
cfg_has_const_mutex_new! {
pub(crate) fn next() -> Self {
use crate::loom::sync::Mutex;
static NEXT_ID: Mutex<u64> = Mutex::const_new(1);

let mut lock = NEXT_ID.lock();
let id = *lock;
*lock += 1;
Self(id)
}
}

static NEXT_ID: OnceCell<Mutex<u64>> = OnceCell::new();
cfg_not_has_const_mutex_new! {
pub(crate) fn next() -> Self {
use crate::util::once_cell::OnceCell;
use crate::loom::sync::Mutex;

let next_id = NEXT_ID.get(init_next_id);
let mut lock = next_id.lock();
let id = *lock;
*lock += 1;
Self(id)
fn init_next_id() -> Mutex<u64> {
Mutex::new(1)
}

static NEXT_ID: OnceCell<Mutex<u64>> = OnceCell::new();

let next_id = NEXT_ID.get(init_next_id);
let mut lock = next_id.lock();
let id = *lock;
*lock += 1;
Self(id)
}
}
}

Expand Down
10 changes: 2 additions & 8 deletions tokio/src/util/mod.rs
Expand Up @@ -6,14 +6,8 @@ cfg_io_driver! {
#[cfg(feature = "rt")]
pub(crate) mod atomic_cell;

cfg_has_atomic_u64! {
#[cfg(any(feature = "signal", all(unix, feature = "process")))]
pub(crate) mod once_cell;
}
cfg_not_has_atomic_u64! {
#[cfg(any(feature = "rt", feature = "signal", all(unix, feature = "process")))]
pub(crate) mod once_cell;
}
#[cfg(any(feature = "rt", feature = "signal", feature = "process"))]
pub(crate) mod once_cell;

#[cfg(any(
// io driver uses `WakeList` directly
Expand Down
2 changes: 1 addition & 1 deletion tokio/src/util/once_cell.rs
@@ -1,4 +1,4 @@
#![cfg_attr(loom, allow(dead_code))]
#![allow(dead_code)]
use std::cell::UnsafeCell;
use std::mem::MaybeUninit;
use std::sync::Once;
Expand Down

0 comments on commit f4e08ae

Please sign in to comment.