Skip to content

Commit

Permalink
Merge #24
Browse files Browse the repository at this point in the history
24: Provide stable equivalent of #![feature(atomic_bool_fetch_not)] r=taiki-e a=taiki-e

This provides stable equivalent of [`#![feature(atomic_bool_fetch_not)]`](rust-lang/rust#98485).

- `AtomicBool::fetch_not`

Co-authored-by: Taiki Endo <te316e89@gmail.com>
  • Loading branch information
bors[bot] and taiki-e authored Jul 31, 2022
2 parents f657900 + 99e87e7 commit 802f3d6
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 4 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ Note: In this file, do not use the hard wrap in the middle of a sentence for com
These APIs are compatible with strict-provenance on `cfg(miri)`. Otherwise, they are compatible with permissive-provenance.
Once `#![feature(strict_provenance_atomic_ptr)]` is stabilized, these APIs will be strict-provenance compatible in all cases from the version in which it is stabilized.

- Provide stable equivalent of [`#![feature(atomic_bool_fetch_not)]`](https://github.com/rust-lang/rust/issues/98485). ([#24](https://github.com/taiki-e/portable-atomic/pull/24))

- `AtomicBool::fetch_not`

- Optimize x86_64 128-bit RMWs. ([#22](https://github.com/taiki-e/portable-atomic/pull/22))

- Optimize x86_64 outline-atomics.
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ Portable atomic types including support for 128-bit atomics, atomic float, etc.
<!-- - Provide generic `Atomic<T>` type. (optional) -->
- Provide atomic load/store for targets where atomic is not available at all in the standard library. (riscv without A-extension, msp430, avr)
- Provide atomic CAS for targets where atomic CAS is not available in the standard library. (thumbv6m, riscv without A-extension, msp430, avr) (optional, [single-core only](#optional-cfg))
- Provide stable equivalents of the standard library atomic types' unstable APIs, such as [`AtomicPtr::fetch_*`](https://github.com/rust-lang/rust/issues/99108).
- Provide stable equivalents of the standard library atomic types' unstable APIs, such as [`AtomicPtr::fetch_*`](https://github.com/rust-lang/rust/issues/99108), [`AtomicBool::fetch_not`](https://github.com/rust-lang/rust/issues/98485).
- Make features that require newer compilers, such as [fetch_max](https://doc.rust-lang.org/std/sync/atomic/struct.AtomicUsize.html#method.fetch_max), [fetch_min](https://doc.rust-lang.org/std/sync/atomic/struct.AtomicUsize.html#method.fetch_min), [fetch_update](https://doc.rust-lang.org/nightly/std/sync/atomic/struct.AtomicPtr.html#method.fetch_update), and [stronger CAS failure ordering](https://github.com/rust-lang/rust/pull/98383) available on Rust 1.34+.

## 128-bit atomics support
Expand Down
42 changes: 39 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Portable atomic types including support for 128-bit atomics, atomic float, etc.
<!-- - Provide generic `Atomic<T>` type. (optional) -->
- Provide atomic load/store for targets where atomic is not available at all in the standard library. (riscv without A-extension, msp430, avr)
- Provide atomic CAS for targets where atomic CAS is not available in the standard library. (thumbv6m, riscv without A-extension, msp430, avr) (optional, [single-core only](#optional-cfg))
- Provide stable equivalents of the standard library atomic types' unstable APIs, such as [`AtomicPtr::fetch_*`](https://github.com/rust-lang/rust/issues/99108).
- Provide stable equivalents of the standard library atomic types' unstable APIs, such as [`AtomicPtr::fetch_*`](https://github.com/rust-lang/rust/issues/99108), [`AtomicBool::fetch_not`](https://github.com/rust-lang/rust/issues/98485).
- Make features that require newer compilers, such as [fetch_max](https://doc.rust-lang.org/std/sync/atomic/struct.AtomicUsize.html#method.fetch_max), [fetch_min](https://doc.rust-lang.org/std/sync/atomic/struct.AtomicUsize.html#method.fetch_min), [fetch_update](https://doc.rust-lang.org/nightly/std/sync/atomic/struct.AtomicPtr.html#method.fetch_update), and [stronger CAS failure ordering](https://github.com/rust-lang/rust/pull/98383) available on Rust 1.34+.
## 128-bit atomics support
Expand Down Expand Up @@ -778,8 +778,44 @@ impl AtomicBool {
self.inner.fetch_xor(val, order)
}

// TODO: Add fetch_not once it is stable on std atomic types.
// https://github.com/rust-lang/rust/issues/98485
/// Logical "not" with a boolean value.
///
/// Performs a logical "not" operation on the current value, and sets
/// the new value to the result.
///
/// Returns the previous value.
///
/// `fetch_not` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. All ordering modes are possible. Note that using
/// [`Acquire`] makes the store part of this operation [`Relaxed`], and
/// using [`Release`] makes the load part [`Relaxed`].
///
/// # Examples
///
/// ```
/// use portable_atomic::{AtomicBool, Ordering};
///
/// let foo = AtomicBool::new(true);
/// assert_eq!(foo.fetch_not(Ordering::SeqCst), true);
/// assert_eq!(foo.load(Ordering::SeqCst), false);
///
/// let foo = AtomicBool::new(false);
/// assert_eq!(foo.fetch_not(Ordering::SeqCst), false);
/// assert_eq!(foo.load(Ordering::SeqCst), true);
/// ```
#[cfg_attr(
portable_atomic_no_cfg_target_has_atomic,
cfg(any(not(portable_atomic_no_atomic_cas), portable_atomic_unsafe_assume_single_core))
)]
#[cfg_attr(
not(portable_atomic_no_cfg_target_has_atomic),
cfg(any(target_has_atomic = "ptr", portable_atomic_unsafe_assume_single_core))
)]
#[inline]
pub fn fetch_not(&self, order: Ordering) -> bool {
self.fetch_xor(true, order)
}

// TODO: Add as_mut_ptr once it is stable on std atomic types.
// https://github.com/rust-lang/rust/issues/66893

Expand Down
24 changes: 24 additions & 0 deletions src/tests/helper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -941,6 +941,19 @@ macro_rules! __test_atomic_bool {
assert_eq!(a.load(Ordering::Relaxed), false);
}
}
#[test]
fn fetch_not() {
let a = <$atomic_type>::new(true);
test_swap_ordering(|order| a.fetch_not(order));
for order in swap_orderings() {
let a = <$atomic_type>::new(true);
assert_eq!(a.fetch_not(order), true);
assert_eq!(a.load(Ordering::Relaxed), false);
let a = <$atomic_type>::new(false);
assert_eq!(a.fetch_not(order), false);
assert_eq!(a.load(Ordering::Relaxed), true);
}
}
mod quickcheck {
use super::super::*;
use crate::tests::helper::*;
Expand Down Expand Up @@ -1008,6 +1021,17 @@ macro_rules! __test_atomic_bool {
}
true
}
fn fetch_not(x: bool, y: bool) -> bool {
for order in swap_orderings() {
let a = <$atomic_type>::new(x);
assert_eq!(a.fetch_not(order), x);
assert_eq!(a.load(Ordering::Relaxed), !x);
let a = <$atomic_type>::new(y);
assert_eq!(a.fetch_not(order), y);
assert_eq!(a.load(Ordering::Relaxed), !y);
}
true
}
}
}
};
Expand Down

0 comments on commit 802f3d6

Please sign in to comment.