Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replace atomic-shim::AtomicU64 with crossbeam-utils::atomic::AtomicCell<u64> #52

Merged
merged 1 commit into from
Aug 4, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 1 addition & 7 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,20 +34,14 @@ 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"

[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"

Expand Down
38 changes: 12 additions & 26 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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"))]
Expand All @@ -149,19 +146,7 @@ use self::stats::Variance;

static GLOBAL_CLOCK: OnceCell<Clock> = 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<u64> = AtomicCell::new(0);

static GLOBAL_CALIBRATION: OnceCell<Calibration> = OnceCell::new();

Expand All @@ -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<u64>, Monotonic, Counter, Calibration),
Mock(Arc<Mock>),
}

Expand Down Expand Up @@ -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)
};
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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()),
}
}

Expand All @@ -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);
}
}

Expand All @@ -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,
Expand Down Expand Up @@ -530,7 +516,7 @@ pub fn with_clock<T>(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]
Expand All @@ -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 {
Expand Down
19 changes: 7 additions & 12 deletions src/mock.rs
Original file line number Diff line number Diff line change
@@ -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.
///
Expand Down Expand Up @@ -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<AtomicU64>,
offset: Arc<AtomicCell<u64>>,
}

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<N: IntoNanoseconds>(&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<N: IntoNanoseconds>(&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()
}
}