From 9f4eb7b94c4b3d7bd681b83e1796c3af39295d0e Mon Sep 17 00:00:00 2001 From: Paolo Barbolini Date: Wed, 4 Aug 2021 16:08:22 +0200 Subject: [PATCH] Replace `atomic-shim::AtomicU64` with `crossbeam-utils::atomic::AtomicCell` --- Cargo.toml | 8 +------- src/lib.rs | 38 ++++++++++++-------------------------- src/mock.rs | 19 +++++++------------ 3 files changed, 20 insertions(+), 45 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 8cc3fc6..4150af8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -34,7 +34,7 @@ prost = ["prost-types"] [dependencies] once_cell = "1.4" prost-types = { version = "0.7", optional = true } -atomic-shim = "0.1.0" +crossbeam-utils = "0.8" [target.'cfg(target_arch = "x86")'.dependencies] raw-cpuid = "9.0" @@ -42,12 +42,6 @@ raw-cpuid = "9.0" [target.'cfg(target_arch = "x86_64")'.dependencies] raw-cpuid = "9.0" -[target.'cfg(target_arch = "mips")'.dependencies] -ctor = "0.1" - -[target.'cfg(target_arch = "powerpc")'.dependencies] -ctor = "0.1" - [target.'cfg(all(not(target_os = "macos"), not(target_os = "ios"), not(target_os = "windows"), not(target_arch = "wasm32")))'.dependencies] libc = "0.2" diff --git a/src/lib.rs b/src/lib.rs index c9bcb7c..71057e5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -123,12 +123,9 @@ //! [clock_gettime]: https://linux.die.net/man/3/clock_gettime //! [prost_types_timestamp]: https://docs.rs/prost-types/0.7.0/prost_types/struct.Timestamp.html //! [windows.performance.now]: https://developer.mozilla.org/en-US/docs/Web/API/Performance/now -use atomic_shim::AtomicU64; +use crossbeam_utils::atomic::AtomicCell; use std::time::Duration; -use std::{ - cell::RefCell, - sync::{atomic::Ordering, Arc}, -}; +use std::{cell::RefCell, sync::Arc}; use once_cell::sync::OnceCell; #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] @@ -149,19 +146,7 @@ use self::stats::Variance; static GLOBAL_CLOCK: OnceCell = OnceCell::new(); -#[cfg(any(target_arch = "mips", target_arch = "powerpc"))] -mod atomic_compat { - use super::AtomicU64; - use ctor::ctor; - - #[ctor] - pub static GLOBAL_RECENT: AtomicU64 = AtomicU64::new(0); -} -#[cfg(any(target_arch = "mips", target_arch = "powerpc"))] -use self::atomic_compat::GLOBAL_RECENT; - -#[cfg(not(any(target_arch = "mips", target_arch = "powerpc")))] -static GLOBAL_RECENT: AtomicU64 = AtomicU64::new(0); +static GLOBAL_RECENT: AtomicCell = AtomicCell::new(0); static GLOBAL_CALIBRATION: OnceCell = OnceCell::new(); @@ -182,7 +167,7 @@ const MAXIMUM_CAL_TIME: Duration = Duration::from_millis(200); #[derive(Debug)] enum ClockType { Monotonic(Monotonic), - Counter(AtomicU64, Monotonic, Counter, Calibration), + Counter(AtomicCell, Monotonic, Counter, Calibration), Mock(Arc), } @@ -317,7 +302,7 @@ impl Clock { calibration.calibrate(&reference, &source); calibration }); - ClockType::Counter(AtomicU64::new(0), reference, source, *calibration) + ClockType::Counter(AtomicCell::new(0), reference, source, *calibration) } else { ClockType::Monotonic(reference) }; @@ -351,7 +336,8 @@ impl Clock { let now = counter.now(); // Update the last timestamp with `now`, if `now` is greater // than the current value. - let last = last.fetch_max(now, Ordering::AcqRel); + // TODO: replace with `AtomicCell::fetch_max` once `crossbeam-utils` implements it. + let last = last.fetch_update(|current| Some(current.max(now))).unwrap(); // `fetch_max` always returns the previous value, so we need to // see which is *actually* the max. let actual = std::cmp::max(now, last); @@ -476,7 +462,7 @@ impl Clock { pub fn recent(&self) -> Instant { match &self.inner { ClockType::Mock(mock) => Instant(mock.value()), - _ => Instant(GLOBAL_RECENT.load(Ordering::Relaxed)), + _ => Instant(GLOBAL_RECENT.load()), } } @@ -485,7 +471,7 @@ impl Clock { /// Most callers should use the existing [`Builder`] machinery for spawning a background thread /// to handle upkeep, rather than calling [`upkeep`] directly. pub fn upkeep(value: Instant) { - GLOBAL_RECENT.store(value.0, Ordering::Release); + GLOBAL_RECENT.store(value.0); } } @@ -502,7 +488,7 @@ impl Clone for ClockType { ClockType::Mock(mock) => ClockType::Mock(mock.clone()), ClockType::Monotonic(monotonic) => ClockType::Monotonic(monotonic.clone()), ClockType::Counter(last, monotonic, counter, calibration) => ClockType::Counter( - AtomicU64::new(last.load(Ordering::Acquire)), + AtomicCell::new(last.load()), monotonic.clone(), counter.clone(), *calibration, @@ -530,7 +516,7 @@ pub fn with_clock(clock: &Clock, f: impl FnOnce() -> T) -> T { /// recent time is updated. For example, programs using an asynchronous runtime may prefer to /// schedule a task that does the updating, avoiding an extra thread. pub fn set_recent(instant: Instant) { - GLOBAL_RECENT.store(instant.as_u64(), Ordering::Release); + GLOBAL_RECENT.store(instant.as_u64()); } #[inline] @@ -550,7 +536,7 @@ pub(crate) fn get_recent() -> Instant { // // Given that global recent time shouldn't ever be getting _actually_ updated in tests, this // should be a reasonable trade-off. - let recent = GLOBAL_RECENT.load(Ordering::Acquire); + let recent = GLOBAL_RECENT.load(); if recent != 0 { Instant(recent) } else { diff --git a/src/mock.rs b/src/mock.rs index a11cbcf..d730496 100644 --- a/src/mock.rs +++ b/src/mock.rs @@ -1,9 +1,6 @@ #![allow(dead_code)] -use atomic_shim::AtomicU64; -use std::{ - sync::{atomic::Ordering, Arc}, - time::Duration, -}; +use crossbeam_utils::atomic::AtomicCell; +use std::{sync::Arc, time::Duration}; /// Type which can be converted into a nanosecond representation. /// @@ -36,30 +33,28 @@ impl IntoNanoseconds for Duration { /// testing that code can handle large shifts in time. #[derive(Debug, Clone)] pub struct Mock { - offset: Arc, + offset: Arc>, } impl Mock { pub(crate) fn new() -> Self { Self { - offset: Arc::new(AtomicU64::new(0)), + offset: Arc::new(AtomicCell::new(0)), } } /// Increments the time by the given amount. pub fn increment(&self, amount: N) { - self.offset - .fetch_add(amount.into_nanos(), Ordering::Release); + self.offset.fetch_add(amount.into_nanos()); } /// Decrements the time by the given amount. pub fn decrement(&self, amount: N) { - self.offset - .fetch_sub(amount.into_nanos(), Ordering::Release); + self.offset.fetch_sub(amount.into_nanos()); } /// Gets the current value of this `Mock`. pub fn value(&self) -> u64 { - self.offset.load(Ordering::Acquire) + self.offset.load() } }