diff --git a/tokio/src/loom/std/mutex.rs b/tokio/src/loom/std/mutex.rs index 7b8f9ba1e24..2a56cff4666 100644 --- a/tokio/src/loom/std/mutex.rs +++ b/tokio/src/loom/std/mutex.rs @@ -8,8 +8,8 @@ pub(crate) struct Mutex(sync::Mutex); #[allow(dead_code)] impl Mutex { #[inline] - pub(crate) fn new(t: T) -> Mutex { - Mutex(sync::Mutex::new(t)) + pub(crate) const fn new(t: T) -> Mutex { + Self::const_new(t) } #[inline] diff --git a/tokio/src/loom/std/parking_lot.rs b/tokio/src/loom/std/parking_lot.rs index e3af258d116..f592954d43a 100644 --- a/tokio/src/loom/std/parking_lot.rs +++ b/tokio/src/loom/std/parking_lot.rs @@ -47,8 +47,8 @@ pub(crate) struct RwLockWriteGuard<'a, T: ?Sized>( impl Mutex { #[inline] - pub(crate) fn new(t: T) -> Mutex { - Mutex(PhantomData, parking_lot::Mutex::new(t)) + pub(crate) const fn new(t: T) -> Mutex { + Self::const_new(t) } #[inline] diff --git a/tokio/src/macros/cfg.rs b/tokio/src/macros/cfg.rs index 2862e1f55b4..c6638fa091d 100644 --- a/tokio/src/macros/cfg.rs +++ b/tokio/src/macros/cfg.rs @@ -556,6 +556,18 @@ macro_rules! cfg_not_has_const_mutex_new { } } +macro_rules! cfg_const_if_has_const_mutex_new { + ($(#[$attr:meta])* $vis:vis const fn $fn_name:ident $( $rest : tt )*) => { + #[cfg(not(all(loom, test)))] + $(#[$attr])* + $vis const fn $fn_name $( $rest )* + + #[cfg(all(loom, test))] + $(#[$attr])* + $vis fn $fn_name $( $rest )* + } +} + macro_rules! cfg_not_wasi { ($($item:item)*) => { $( diff --git a/tokio/src/sync/batch_semaphore.rs b/tokio/src/sync/batch_semaphore.rs index e0dafaa256e..8eab68f3fae 100644 --- a/tokio/src/sync/batch_semaphore.rs +++ b/tokio/src/sync/batch_semaphore.rs @@ -135,43 +135,22 @@ impl Semaphore { // PERMIT_SHIFT is used to leave that bit for that purpose. const PERMIT_SHIFT: usize = 1; - /// Creates a new semaphore with the initial number of permits - /// - /// Maximum number of permits on 32-bit platforms is `1<<29`. - pub(crate) fn new(permits: usize) -> Self { - assert!( - permits <= Self::MAX_PERMITS, - "a semaphore may not have more than MAX_PERMITS permits ({})", - Self::MAX_PERMITS - ); - - #[cfg(all(tokio_unstable, feature = "tracing"))] - let resource_span = { - let resource_span = tracing::trace_span!( - "runtime.resource", - concrete_type = "Semaphore", - kind = "Sync", - is_internal = true - ); - - resource_span.in_scope(|| { - tracing::trace!( - target: "runtime::resource::state_update", - permits = permits, - permits.op = "override", - ) - }); - resource_span - }; + cfg_const_if_has_const_mutex_new! { + /// Creates a new semaphore with the initial number of permits + /// + /// Maximum number of permits on 32-bit platforms is `1<<29`. + pub(crate) const fn new(permits: usize) -> Self { + assert!(permits <= Self::MAX_PERMITS); - Self { - permits: AtomicUsize::new(permits << Self::PERMIT_SHIFT), - waiters: Mutex::new(Waitlist { - queue: LinkedList::new(), - closed: false, - }), - #[cfg(all(tokio_unstable, feature = "tracing"))] - resource_span, + Self { + permits: AtomicUsize::new(permits << Self::PERMIT_SHIFT), + waiters: Mutex::new(Waitlist { + queue: LinkedList::new(), + closed: false, + }), + #[cfg(all(tokio_unstable, feature = "tracing"))] + resource_span: tracing::Span::none(), + } } } @@ -180,17 +159,7 @@ impl Semaphore { /// Maximum number of permits on 32-bit platforms is `1<<29`. #[cfg(not(all(loom, test)))] pub(crate) const fn const_new(permits: usize) -> Self { - assert!(permits <= Self::MAX_PERMITS); - - Self { - permits: AtomicUsize::new(permits << Self::PERMIT_SHIFT), - waiters: Mutex::const_new(Waitlist { - queue: LinkedList::new(), - closed: false, - }), - #[cfg(all(tokio_unstable, feature = "tracing"))] - resource_span: tracing::Span::none(), - } + Self::new(permits) } /// Creates a new closed semaphore with 0 permits. diff --git a/tokio/src/sync/mutex.rs b/tokio/src/sync/mutex.rs index 0700c260eb2..c8b20d3923f 100644 --- a/tokio/src/sync/mutex.rs +++ b/tokio/src/sync/mutex.rs @@ -321,51 +321,27 @@ fn bounds() { } impl Mutex { - /// Creates a new lock in an unlocked state ready for use. - /// - /// # Examples - /// - /// ``` - /// use tokio::sync::Mutex; - /// - /// let lock = Mutex::new(5); - /// ``` - #[track_caller] - pub fn new(t: T) -> Self - where - T: Sized, - { - #[cfg(all(tokio_unstable, feature = "tracing"))] - let resource_span = { - let location = std::panic::Location::caller(); - - tracing::trace_span!( - "runtime.resource", - concrete_type = "Mutex", - kind = "Sync", - loc.file = location.file(), - loc.line = location.line(), - loc.col = location.column(), - ) - }; - - #[cfg(all(tokio_unstable, feature = "tracing"))] - let s = resource_span.in_scope(|| { - tracing::trace!( - target: "runtime::resource::state_update", - locked = false, - ); - semaphore::Semaphore::new(1) - }); - - #[cfg(any(not(tokio_unstable), not(feature = "tracing")))] - let s = semaphore::Semaphore::new(1); - - Self { - c: UnsafeCell::new(t), - s, - #[cfg(all(tokio_unstable, feature = "tracing"))] - resource_span, + cfg_const_if_has_const_mutex_new! { + /// Creates a new lock in an unlocked state ready for use. + /// + /// # Examples + /// + /// ``` + /// use tokio::sync::Mutex; + /// + /// let lock = Mutex::new(5); + /// ``` + #[track_caller] + pub const fn new(t: T) -> Self + where + T: Sized, + { + Self { + c: UnsafeCell::new(t), + s: semaphore::Semaphore::new(1), + #[cfg(all(tokio_unstable, feature = "tracing"))] + resource_span: tracing::Span::none(), + } } } @@ -383,12 +359,7 @@ impl Mutex { where T: Sized, { - Self { - c: UnsafeCell::new(t), - s: semaphore::Semaphore::const_new(1), - #[cfg(all(tokio_unstable, feature = "tracing"))] - resource_span: tracing::Span::none(), - } + Self::new(t) } /// Locks this mutex, causing the current task to yield until the lock has diff --git a/tokio/src/sync/notify.rs b/tokio/src/sync/notify.rs index bf00ca3f64f..ee9e4f5b3b9 100644 --- a/tokio/src/sync/notify.rs +++ b/tokio/src/sync/notify.rs @@ -418,19 +418,21 @@ fn atomic_inc_num_notify_waiters_calls(data: &AtomicUsize) { } impl Notify { - /// Create a new `Notify`, initialized without a permit. - /// - /// # Examples - /// - /// ``` - /// use tokio::sync::Notify; - /// - /// let notify = Notify::new(); - /// ``` - pub fn new() -> Notify { - Notify { - state: AtomicUsize::new(0), - waiters: Mutex::new(LinkedList::new()), + cfg_const_if_has_const_mutex_new! { + /// Create a new `Notify`, initialized without a permit. + /// + /// # Examples + /// + /// ``` + /// use tokio::sync::Notify; + /// + /// let notify = Notify::new(); + /// ``` + pub const fn new() -> Notify { + Notify { + state: AtomicUsize::new(0), + waiters: Mutex::new(LinkedList::new()), + } } } @@ -445,10 +447,7 @@ impl Notify { /// ``` #[cfg(not(all(loom, test)))] pub const fn const_new() -> Notify { - Notify { - state: AtomicUsize::new(0), - waiters: Mutex::const_new(LinkedList::new()), - } + Self::const_new() } /// Wait for a notification. diff --git a/tokio/src/sync/once_cell.rs b/tokio/src/sync/once_cell.rs index 8a5463a3be7..d475420646c 100644 --- a/tokio/src/sync/once_cell.rs +++ b/tokio/src/sync/once_cell.rs @@ -123,12 +123,14 @@ impl From for OnceCell { } impl OnceCell { - /// Creates a new empty `OnceCell` instance. - pub fn new() -> Self { - OnceCell { - value_set: AtomicBool::new(false), - value: UnsafeCell::new(MaybeUninit::uninit()), - semaphore: Semaphore::new(1), + cfg_const_if_has_const_mutex_new! { + /// Creates a new empty `OnceCell` instance. + pub const fn new() -> Self { + OnceCell { + value_set: AtomicBool::new(false), + value: UnsafeCell::new(MaybeUninit::uninit()), + semaphore: Semaphore::new(1), + } } } @@ -175,11 +177,7 @@ impl OnceCell { /// ``` #[cfg(not(all(loom, test)))] pub const fn const_new() -> Self { - OnceCell { - value_set: AtomicBool::new(false), - value: UnsafeCell::new(MaybeUninit::uninit()), - semaphore: Semaphore::const_new(1), - } + Self::new() } /// Returns `true` if the `OnceCell` currently contains a value, and `false` diff --git a/tokio/src/sync/rwlock.rs b/tokio/src/sync/rwlock.rs index ba464eab939..cccdf4d8bbb 100644 --- a/tokio/src/sync/rwlock.rs +++ b/tokio/src/sync/rwlock.rs @@ -191,137 +191,54 @@ where } impl RwLock { - /// Creates a new instance of an `RwLock` which is unlocked. - /// - /// # Examples - /// - /// ``` - /// use tokio::sync::RwLock; - /// - /// let lock = RwLock::new(5); - /// ``` - #[track_caller] - pub fn new(value: T) -> RwLock - where - T: Sized, - { - #[cfg(all(tokio_unstable, feature = "tracing"))] - let resource_span = { - let location = std::panic::Location::caller(); - let resource_span = tracing::trace_span!( - "runtime.resource", - concrete_type = "RwLock", - kind = "Sync", - loc.file = location.file(), - loc.line = location.line(), - loc.col = location.column(), - ); - - resource_span.in_scope(|| { - tracing::trace!( - target: "runtime::resource::state_update", - max_readers = MAX_READS, - ); - - tracing::trace!( - target: "runtime::resource::state_update", - write_locked = false, - ); - - tracing::trace!( - target: "runtime::resource::state_update", - current_readers = 0, - ); - }); - - resource_span - }; - - #[cfg(all(tokio_unstable, feature = "tracing"))] - let s = resource_span.in_scope(|| Semaphore::new(MAX_READS as usize)); - - #[cfg(any(not(tokio_unstable), not(feature = "tracing")))] - let s = Semaphore::new(MAX_READS as usize); - - RwLock { - mr: MAX_READS, - c: UnsafeCell::new(value), - s, - #[cfg(all(tokio_unstable, feature = "tracing"))] - resource_span, + cfg_const_if_has_const_mutex_new! { + /// Creates a new instance of an `RwLock` which is unlocked. + /// + /// # Examples + /// + /// ``` + /// use tokio::sync::RwLock; + /// + /// let lock = RwLock::new(5); + /// ``` + #[track_caller] + pub const fn new(value: T) -> RwLock + where + T: Sized, + { + Self::with_max_readers(value, MAX_READS) } } - /// Creates a new instance of an `RwLock` which is unlocked - /// and allows a maximum of `max_reads` concurrent readers. - /// - /// # Examples - /// - /// ``` - /// use tokio::sync::RwLock; - /// - /// let lock = RwLock::with_max_readers(5, 1024); - /// ``` - /// - /// # Panics - /// - /// Panics if `max_reads` is more than `u32::MAX >> 3`. - #[track_caller] - pub fn with_max_readers(value: T, max_reads: u32) -> RwLock - where - T: Sized, - { - assert!( - max_reads <= MAX_READS, - "a RwLock may not be created with more than {} readers", - MAX_READS - ); - - #[cfg(all(tokio_unstable, feature = "tracing"))] - let resource_span = { - let location = std::panic::Location::caller(); - - let resource_span = tracing::trace_span!( - "runtime.resource", - concrete_type = "RwLock", - kind = "Sync", - loc.file = location.file(), - loc.line = location.line(), - loc.col = location.column(), - ); - - resource_span.in_scope(|| { - tracing::trace!( - target: "runtime::resource::state_update", - max_readers = max_reads, - ); - - tracing::trace!( - target: "runtime::resource::state_update", - write_locked = false, - ); - - tracing::trace!( - target: "runtime::resource::state_update", - current_readers = 0, - ); - }); - - resource_span - }; - - #[cfg(all(tokio_unstable, feature = "tracing"))] - let s = resource_span.in_scope(|| Semaphore::new(max_reads as usize)); - - #[cfg(any(not(tokio_unstable), not(feature = "tracing")))] - let s = Semaphore::new(max_reads as usize); - - RwLock { - mr: max_reads, - c: UnsafeCell::new(value), - s, - #[cfg(all(tokio_unstable, feature = "tracing"))] - resource_span, + cfg_const_if_has_const_mutex_new! { + /// Creates a new instance of an `RwLock` which is unlocked + /// and allows a maximum of `max_reads` concurrent readers. + /// + /// # Examples + /// + /// ``` + /// use tokio::sync::RwLock; + /// + /// let lock = RwLock::with_max_readers(5, 1024); + /// ``` + /// + /// # Panics + /// + /// Panics if `max_reads` is more than `u32::MAX >> 3`. + #[track_caller] + pub const fn with_max_readers(value: T, max_reads: u32) -> RwLock + where + T: Sized, + { + assert!(max_reads <= MAX_READS); + + RwLock { + mr: max_reads, + c: UnsafeCell::new(value), + s: Semaphore::new(max_reads as usize), + #[cfg(all(tokio_unstable, feature = "tracing"))] + resource_span: tracing::Span::none(), + } } } @@ -339,13 +256,7 @@ impl RwLock { where T: Sized, { - RwLock { - mr: MAX_READS, - c: UnsafeCell::new(value), - s: Semaphore::const_new(MAX_READS as usize), - #[cfg(all(tokio_unstable, feature = "tracing"))] - resource_span: tracing::Span::none(), - } + Self::new(value) } /// Creates a new instance of an `RwLock` which is unlocked @@ -363,15 +274,7 @@ impl RwLock { where T: Sized, { - assert!(max_reads <= MAX_READS); - - RwLock { - mr: max_reads, - c: UnsafeCell::new(value), - s: Semaphore::const_new(max_reads as usize), - #[cfg(all(tokio_unstable, feature = "tracing"))] - resource_span: tracing::Span::none(), - } + Self::with_max_readers(value, max_reads) } /// Locks this `RwLock` with shared read access, causing the current task diff --git a/tokio/src/sync/semaphore.rs b/tokio/src/sync/semaphore.rs index cb770215488..7a5e4894681 100644 --- a/tokio/src/sync/semaphore.rs +++ b/tokio/src/sync/semaphore.rs @@ -130,36 +130,17 @@ impl Semaphore { /// Exceeding this limit typically results in a panic. pub const MAX_PERMITS: usize = super::batch_semaphore::Semaphore::MAX_PERMITS; - /// Creates a new semaphore with the initial number of permits. - /// - /// Panics if `permits` exceeds [`Semaphore::MAX_PERMITS`]. - #[track_caller] - pub fn new(permits: usize) -> Self { - #[cfg(all(tokio_unstable, feature = "tracing"))] - let resource_span = { - let location = std::panic::Location::caller(); - - tracing::trace_span!( - "runtime.resource", - concrete_type = "Semaphore", - kind = "Sync", - loc.file = location.file(), - loc.line = location.line(), - loc.col = location.column(), - inherits_child_attrs = true, - ) - }; - - #[cfg(all(tokio_unstable, feature = "tracing"))] - let ll_sem = resource_span.in_scope(|| ll::Semaphore::new(permits)); - - #[cfg(any(not(tokio_unstable), not(feature = "tracing")))] - let ll_sem = ll::Semaphore::new(permits); - - Self { - ll_sem, - #[cfg(all(tokio_unstable, feature = "tracing"))] - resource_span, + cfg_const_if_has_const_mutex_new! { + /// Creates a new semaphore with the initial number of permits. + /// + /// Panics if `permits` exceeds [`Semaphore::MAX_PERMITS`]. + #[track_caller] + pub const fn new(permits: usize) -> Self { + Self { + ll_sem: ll::Semaphore::new(permits), + #[cfg(all(tokio_unstable, feature = "tracing"))] + resource_span: tracing::Span::none(), + } } } @@ -174,11 +155,7 @@ impl Semaphore { /// ``` #[cfg(not(all(loom, test)))] pub const fn const_new(permits: usize) -> Self { - Self { - ll_sem: ll::Semaphore::const_new(permits), - #[cfg(all(tokio_unstable, feature = "tracing"))] - resource_span: tracing::Span::none(), - } + Self::new(permits) } /// Creates a new closed semaphore with 0 permits.