Skip to content

Commit

Permalink
Merge #767
Browse files Browse the repository at this point in the history
767: Support AtomicCell<*64> arithmetics on targets that do not support Atomic*64 r=taiki-e a=taiki-e

This adds `AtomicCell<{i,u}64>::{fetch_add,fetch_sub,fetch_and,fetch_or,fetch_xor}` on targets that do not support `Atomic{I,U}64`.
This also adds `AtomicCell<{i,u}128>::{fetch_add,fetch_sub,fetch_and,fetch_or,fetch_xor}`.

These were provided in older versions of crossbeam-utils, but were unintentionally removed in 0.8.0 (11fbf05).

Co-authored-by: Taiki Endo <te316e89@gmail.com>
  • Loading branch information
bors[bot] and taiki-e authored Jan 8, 2022
2 parents ed4b555 + 3db81f9 commit d77e702
Showing 1 changed file with 42 additions and 21 deletions.
63 changes: 42 additions & 21 deletions crossbeam-utils/src/atomic/atomic_cell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@ impl<T: Copy + Eq> AtomicCell<T> {
}

macro_rules! impl_arithmetic {
($t:ty, $example:tt) => {
($t:ty, fallback, $example:tt) => {
impl AtomicCell<$t> {
/// Increments the current value by `val` and returns the previous value.
///
Expand All @@ -313,10 +313,13 @@ macro_rules! impl_arithmetic {
/// ```
#[inline]
pub fn fetch_add(&self, val: $t) -> $t {
if can_transmute::<$t, atomic::AtomicUsize>() {
let a = unsafe { &*(self.value.get() as *const atomic::AtomicUsize) };
a.fetch_add(val as usize, Ordering::AcqRel) as $t
} else {
#[cfg(crossbeam_loom)]
{
let _ = val;
unimplemented!("loom does not support non-atomic atomic ops");
}
#[cfg(not(crossbeam_loom))]
{
let _guard = lock(self.value.get() as usize).write();
let value = unsafe { &mut *(self.value.get()) };
let old = *value;
Expand All @@ -341,10 +344,13 @@ macro_rules! impl_arithmetic {
/// ```
#[inline]
pub fn fetch_sub(&self, val: $t) -> $t {
if can_transmute::<$t, atomic::AtomicUsize>() {
let a = unsafe { &*(self.value.get() as *const atomic::AtomicUsize) };
a.fetch_sub(val as usize, Ordering::AcqRel) as $t
} else {
#[cfg(crossbeam_loom)]
{
let _ = val;
unimplemented!("loom does not support non-atomic atomic ops");
}
#[cfg(not(crossbeam_loom))]
{
let _guard = lock(self.value.get() as usize).write();
let value = unsafe { &mut *(self.value.get()) };
let old = *value;
Expand All @@ -367,10 +373,13 @@ macro_rules! impl_arithmetic {
/// ```
#[inline]
pub fn fetch_and(&self, val: $t) -> $t {
if can_transmute::<$t, atomic::AtomicUsize>() {
let a = unsafe { &*(self.value.get() as *const atomic::AtomicUsize) };
a.fetch_and(val as usize, Ordering::AcqRel) as $t
} else {
#[cfg(crossbeam_loom)]
{
let _ = val;
unimplemented!("loom does not support non-atomic atomic ops");
}
#[cfg(not(crossbeam_loom))]
{
let _guard = lock(self.value.get() as usize).write();
let value = unsafe { &mut *(self.value.get()) };
let old = *value;
Expand All @@ -393,10 +402,13 @@ macro_rules! impl_arithmetic {
/// ```
#[inline]
pub fn fetch_or(&self, val: $t) -> $t {
if can_transmute::<$t, atomic::AtomicUsize>() {
let a = unsafe { &*(self.value.get() as *const atomic::AtomicUsize) };
a.fetch_or(val as usize, Ordering::AcqRel) as $t
} else {
#[cfg(crossbeam_loom)]
{
let _ = val;
unimplemented!("loom does not support non-atomic atomic ops");
}
#[cfg(not(crossbeam_loom))]
{
let _guard = lock(self.value.get() as usize).write();
let value = unsafe { &mut *(self.value.get()) };
let old = *value;
Expand All @@ -419,10 +431,13 @@ macro_rules! impl_arithmetic {
/// ```
#[inline]
pub fn fetch_xor(&self, val: $t) -> $t {
if can_transmute::<$t, atomic::AtomicUsize>() {
let a = unsafe { &*(self.value.get() as *const atomic::AtomicUsize) };
a.fetch_xor(val as usize, Ordering::AcqRel) as $t
} else {
#[cfg(crossbeam_loom)]
{
let _ = val;
unimplemented!("loom does not support non-atomic atomic ops");
}
#[cfg(not(crossbeam_loom))]
{
let _guard = lock(self.value.get() as usize).write();
let value = unsafe { &mut *(self.value.get()) };
let old = *value;
Expand Down Expand Up @@ -541,9 +556,15 @@ impl_arithmetic!(i32, atomic::AtomicI32, "let a = AtomicCell::new(7i32);");
impl_arithmetic!(u64, atomic::AtomicU64, "let a = AtomicCell::new(7u64);");
#[cfg(not(crossbeam_no_atomic_64))]
impl_arithmetic!(i64, atomic::AtomicI64, "let a = AtomicCell::new(7i64);");
#[cfg(crossbeam_no_atomic_64)]
impl_arithmetic!(u64, fallback, "let a = AtomicCell::new(7u64);");
#[cfg(crossbeam_no_atomic_64)]
impl_arithmetic!(i64, fallback, "let a = AtomicCell::new(7i64);");
// 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!(u128, fallback, "let a = AtomicCell::new(7u128);");
impl_arithmetic!(i128, fallback, "let a = AtomicCell::new(7i128);");

impl_arithmetic!(
usize,
Expand Down

0 comments on commit d77e702

Please sign in to comment.