aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJoel Galenson <jgalenson@google.com>2021-06-21 12:24:00 -0700
committerJoel Galenson <jgalenson@google.com>2021-06-21 12:24:00 -0700
commit2ce91674eba239b60b91d77c02fe074e40ed8eda (patch)
treec662582a391e8ddc05a36058307c9d9351ae136a /src
parent0a9d0cd11bb8f8dd61c4a5ec589da5ab9e2a875f (diff)
downloadcrossbeam-utils-2ce91674eba239b60b91d77c02fe074e40ed8eda.tar.gz
Upgrade rust/crates/crossbeam-utils to 0.8.5android-s-beta-4android-s-beta-3android-s-beta-4
Test: make Change-Id: I91b96d177f85c2c962370e14a6cd3a989b447e66
Diffstat (limited to 'src')
-rw-r--r--src/atomic/atomic_cell.rs79
-rw-r--r--src/atomic/consume.rs24
-rw-r--r--src/atomic/mod.rs8
-rw-r--r--src/lib.rs27
4 files changed, 73 insertions, 65 deletions
diff --git a/src/atomic/atomic_cell.rs b/src/atomic/atomic_cell.rs
index ad094b2..1a1c464 100644
--- a/src/atomic/atomic_cell.rs
+++ b/src/atomic/atomic_cell.rs
@@ -258,6 +258,40 @@ impl<T: Copy + Eq> AtomicCell<T> {
pub fn compare_exchange(&self, current: T, new: T) -> Result<T, T> {
unsafe { atomic_compare_exchange_weak(self.value.get(), current, new) }
}
+
+ /// Fetches the value, and applies a function to it that returns an optional
+ /// new value. Returns a `Result` of `Ok(previous_value)` if the function returned `Some(_)`, else
+ /// `Err(previous_value)`.
+ ///
+ /// Note: This may call the function multiple times if the value has been changed from other threads in
+ /// the meantime, as long as the function returns `Some(_)`, but the function will have been applied
+ /// only once to the stored value.
+ ///
+ /// # Examples
+ ///
+ /// ```rust
+ /// use crossbeam_utils::atomic::AtomicCell;
+ ///
+ /// let a = AtomicCell::new(7);
+ /// assert_eq!(a.fetch_update(|_| None), Err(7));
+ /// assert_eq!(a.fetch_update(|a| Some(a + 1)), Ok(7));
+ /// assert_eq!(a.fetch_update(|a| Some(a + 1)), Ok(8));
+ /// assert_eq!(a.load(), 9);
+ /// ```
+ #[inline]
+ pub fn fetch_update<F>(&self, mut f: F) -> Result<T, T>
+ where
+ F: FnMut(T) -> Option<T>,
+ {
+ let mut prev = self.load();
+ while let Some(next) = f(prev) {
+ match self.compare_exchange(prev, next) {
+ x @ Ok(_) => return x,
+ Err(next_prev) => prev = next_prev,
+ }
+ }
+ Err(prev)
+ }
}
macro_rules! impl_arithmetic {
@@ -497,33 +531,25 @@ macro_rules! impl_arithmetic {
};
}
-#[cfg(has_atomic_u8)]
impl_arithmetic!(u8, atomic::AtomicU8, "let a = AtomicCell::new(7u8);");
-#[cfg(all(has_atomic_u8, not(crossbeam_loom)))]
impl_arithmetic!(i8, atomic::AtomicI8, "let a = AtomicCell::new(7i8);");
-#[cfg(has_atomic_u16)]
impl_arithmetic!(u16, atomic::AtomicU16, "let a = AtomicCell::new(7u16);");
-#[cfg(all(has_atomic_u16, not(crossbeam_loom)))]
impl_arithmetic!(i16, atomic::AtomicI16, "let a = AtomicCell::new(7i16);");
-#[cfg(has_atomic_u32)]
impl_arithmetic!(u32, atomic::AtomicU32, "let a = AtomicCell::new(7u32);");
-#[cfg(all(has_atomic_u32, not(crossbeam_loom)))]
impl_arithmetic!(i32, atomic::AtomicI32, "let a = AtomicCell::new(7i32);");
-#[cfg(has_atomic_u64)]
+#[cfg(not(crossbeam_no_atomic_64))]
impl_arithmetic!(u64, atomic::AtomicU64, "let a = AtomicCell::new(7u64);");
-#[cfg(all(has_atomic_u64, not(crossbeam_loom)))]
+#[cfg(not(crossbeam_no_atomic_64))]
impl_arithmetic!(i64, atomic::AtomicI64, "let a = AtomicCell::new(7i64);");
-#[cfg(all(has_atomic_u128, not(crossbeam_loom)))]
-impl_arithmetic!(u128, atomic::AtomicU128, "let a = AtomicCell::new(7u128);");
-#[cfg(all(has_atomic_u128, not(crossbeam_loom)))]
-impl_arithmetic!(i128, atomic::AtomicI128, "let a = AtomicCell::new(7i128);");
+// TODO: AtomicU128 is unstable
+// impl_arithmetic!(u128, atomic::AtomicU128, "let a = AtomicCell::new(7u128);");
+// impl_arithmetic!(i128, atomic::AtomicI128, "let a = AtomicCell::new(7i128);");
impl_arithmetic!(
usize,
atomic::AtomicUsize,
"let a = AtomicCell::new(7usize);"
);
-#[cfg(not(crossbeam_loom))]
impl_arithmetic!(
isize,
atomic::AtomicIsize,
@@ -809,16 +835,13 @@ macro_rules! atomic {
atomic!(@check, $t, AtomicUnit, $a, $atomic_op);
atomic!(@check, $t, atomic::AtomicUsize, $a, $atomic_op);
- #[cfg(has_atomic_u8)]
atomic!(@check, $t, atomic::AtomicU8, $a, $atomic_op);
- #[cfg(has_atomic_u16)]
atomic!(@check, $t, atomic::AtomicU16, $a, $atomic_op);
- #[cfg(has_atomic_u32)]
atomic!(@check, $t, atomic::AtomicU32, $a, $atomic_op);
- #[cfg(has_atomic_u64)]
+ #[cfg(not(crossbeam_no_atomic_64))]
atomic!(@check, $t, atomic::AtomicU64, $a, $atomic_op);
- #[cfg(has_atomic_u128)]
- atomic!(@check, $t, atomic::AtomicU128, $a, $atomic_op);
+ // TODO: AtomicU128 is unstable
+ // atomic!(@check, $t, atomic::AtomicU128, $a, $atomic_op);
#[cfg(crossbeam_loom)]
unimplemented!("loom does not support non-atomic atomic ops");
@@ -831,17 +854,15 @@ macro_rules! atomic {
/// Returns `true` if operations on `AtomicCell<T>` are lock-free.
const fn atomic_is_lock_free<T>() -> bool {
// HACK(taiki-e): This is equivalent to `atomic! { T, _a, true, false }`, but can be used in const fn even in Rust 1.36.
- let is_lock_free = can_transmute::<T, AtomicUnit>() | can_transmute::<T, atomic::AtomicUsize>();
- #[cfg(has_atomic_u8)]
- let is_lock_free = is_lock_free | can_transmute::<T, atomic::AtomicU8>();
- #[cfg(has_atomic_u16)]
- let is_lock_free = is_lock_free | can_transmute::<T, atomic::AtomicU16>();
- #[cfg(has_atomic_u32)]
- let is_lock_free = is_lock_free | can_transmute::<T, atomic::AtomicU32>();
- #[cfg(has_atomic_u64)]
+ let is_lock_free = can_transmute::<T, AtomicUnit>()
+ | can_transmute::<T, atomic::AtomicUsize>()
+ | can_transmute::<T, atomic::AtomicU8>()
+ | can_transmute::<T, atomic::AtomicU16>()
+ | can_transmute::<T, atomic::AtomicU32>();
+ #[cfg(not(crossbeam_no_atomic_64))]
let is_lock_free = is_lock_free | can_transmute::<T, atomic::AtomicU64>();
- #[cfg(has_atomic_u128)]
- let is_lock_free = is_lock_free | can_transmute::<T, atomic::AtomicU128>();
+ // TODO: AtomicU128 is unstable
+ // let is_lock_free = is_lock_free | can_transmute::<T, atomic::AtomicU128>();
is_lock_free
}
diff --git a/src/atomic/consume.rs b/src/atomic/consume.rs
index 0fbd93e..277b370 100644
--- a/src/atomic/consume.rs
+++ b/src/atomic/consume.rs
@@ -1,5 +1,6 @@
#[cfg(any(target_arch = "arm", target_arch = "aarch64"))]
use crate::primitive::sync::atomic::compiler_fence;
+#[cfg(not(crossbeam_no_atomic))]
use core::sync::atomic::Ordering;
/// Trait which allows reading from primitive atomic types with "consume" ordering.
@@ -25,6 +26,7 @@ pub trait AtomicConsume {
fn load_consume(&self) -> Self::Val;
}
+#[cfg(not(crossbeam_no_atomic))]
#[cfg(any(target_arch = "arm", target_arch = "aarch64"))]
macro_rules! impl_consume {
() => {
@@ -37,6 +39,7 @@ macro_rules! impl_consume {
};
}
+#[cfg(not(crossbeam_no_atomic))]
#[cfg(not(any(target_arch = "arm", target_arch = "aarch64")))]
macro_rules! impl_consume {
() => {
@@ -49,12 +52,13 @@ macro_rules! impl_consume {
macro_rules! impl_atomic {
($atomic:ident, $val:ty) => {
- impl AtomicConsume for ::core::sync::atomic::$atomic {
+ #[cfg(not(crossbeam_no_atomic))]
+ impl AtomicConsume for core::sync::atomic::$atomic {
type Val = $val;
impl_consume!();
}
#[cfg(crossbeam_loom)]
- impl AtomicConsume for ::loom::sync::atomic::$atomic {
+ impl AtomicConsume for loom::sync::atomic::$atomic {
type Val = $val;
impl_consume!();
}
@@ -63,32 +67,26 @@ macro_rules! impl_atomic {
impl_atomic!(AtomicBool, bool);
impl_atomic!(AtomicUsize, usize);
-#[cfg(not(crossbeam_loom))]
impl_atomic!(AtomicIsize, isize);
-#[cfg(has_atomic_u8)]
impl_atomic!(AtomicU8, u8);
-#[cfg(has_atomic_u8)]
impl_atomic!(AtomicI8, i8);
-#[cfg(has_atomic_u16)]
impl_atomic!(AtomicU16, u16);
-#[cfg(has_atomic_u16)]
impl_atomic!(AtomicI16, i16);
-#[cfg(has_atomic_u32)]
impl_atomic!(AtomicU32, u32);
-#[cfg(has_atomic_u32)]
impl_atomic!(AtomicI32, i32);
-#[cfg(has_atomic_u64)]
+#[cfg(not(crossbeam_no_atomic_64))]
impl_atomic!(AtomicU64, u64);
-#[cfg(has_atomic_u64)]
+#[cfg(not(crossbeam_no_atomic_64))]
impl_atomic!(AtomicI64, i64);
-impl<T> AtomicConsume for ::core::sync::atomic::AtomicPtr<T> {
+#[cfg(not(crossbeam_no_atomic))]
+impl<T> AtomicConsume for core::sync::atomic::AtomicPtr<T> {
type Val = *mut T;
impl_consume!();
}
#[cfg(crossbeam_loom)]
-impl<T> AtomicConsume for ::loom::sync::atomic::AtomicPtr<T> {
+impl<T> AtomicConsume for loom::sync::atomic::AtomicPtr<T> {
type Val = *mut T;
impl_consume!();
}
diff --git a/src/atomic/mod.rs b/src/atomic/mod.rs
index 874eaf2..fc713fc 100644
--- a/src/atomic/mod.rs
+++ b/src/atomic/mod.rs
@@ -3,11 +3,9 @@
//! * [`AtomicCell`], a thread-safe mutable memory location.
//! * [`AtomicConsume`], for reading from primitive atomic types with "consume" ordering.
+#[cfg(not(crossbeam_no_atomic_cas))]
#[cfg(not(crossbeam_loom))]
-use cfg_if::cfg_if;
-
-#[cfg(not(crossbeam_loom))]
-cfg_if! {
+cfg_if::cfg_if! {
// Use "wide" sequence lock if the pointer width <= 32 for preventing its counter against wrap
// around.
//
@@ -25,8 +23,10 @@ cfg_if! {
}
}
+#[cfg(not(crossbeam_no_atomic_cas))]
mod atomic_cell;
mod consume;
+#[cfg(not(crossbeam_no_atomic_cas))]
pub use self::atomic_cell::AtomicCell;
pub use self::consume::AtomicConsume;
diff --git a/src/lib.rs b/src/lib.rs
index 880d37e..191c5a1 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -38,7 +38,6 @@
unreachable_pub
)]
#![cfg_attr(not(feature = "std"), no_std)]
-#![cfg_attr(feature = "nightly", feature(cfg_target_has_atomic))]
#[cfg(crossbeam_loom)]
#[allow(unused_imports)]
@@ -47,7 +46,8 @@ mod primitive {
pub(crate) mod atomic {
pub(crate) use loom::sync::atomic::spin_loop_hint;
pub(crate) use loom::sync::atomic::{
- AtomicBool, AtomicU16, AtomicU32, AtomicU64, AtomicU8, AtomicUsize,
+ AtomicBool, AtomicI16, AtomicI32, AtomicI64, AtomicI8, AtomicIsize, AtomicU16,
+ AtomicU32, AtomicU64, AtomicU8, AtomicUsize,
};
// FIXME: loom does not support compiler_fence at the moment.
@@ -70,15 +70,13 @@ mod primitive {
// use [`core::hint::spin_loop`] instead.
#[allow(deprecated)]
pub(crate) use core::sync::atomic::spin_loop_hint;
- pub(crate) use core::sync::atomic::{AtomicBool, AtomicIsize, AtomicUsize};
- #[cfg(has_atomic_u16)]
- pub(crate) use core::sync::atomic::{AtomicI16, AtomicU16};
- #[cfg(has_atomic_u32)]
- pub(crate) use core::sync::atomic::{AtomicI32, AtomicU32};
- #[cfg(has_atomic_u64)]
+ #[cfg(not(crossbeam_no_atomic))]
+ pub(crate) use core::sync::atomic::{
+ AtomicBool, AtomicI16, AtomicI32, AtomicI8, AtomicIsize, AtomicU16, AtomicU32,
+ AtomicU8, AtomicUsize,
+ };
+ #[cfg(not(crossbeam_no_atomic_64))]
pub(crate) use core::sync::atomic::{AtomicI64, AtomicU64};
- #[cfg(has_atomic_u8)]
- pub(crate) use core::sync::atomic::{AtomicI8, AtomicU8};
}
#[cfg(feature = "std")]
@@ -86,15 +84,6 @@ mod primitive {
}
}
-cfg_if! {
- if #[cfg(feature = "alloc")] {
- extern crate alloc;
- } else if #[cfg(feature = "std")] {
- extern crate std as alloc;
- }
-}
-
-#[cfg_attr(feature = "nightly", cfg(target_has_atomic = "ptr"))]
pub mod atomic;
mod cache_padded;