mirror of
https://github.com/rust-lang/rust
synced 2024-07-21 02:15:40 +00:00
Rollup merge of #41143 - stjepang:optimize-bool-fetch-nand, r=nagisa
Optimize AtomicBool::fetch_nand This is an attempt to push the PR #40563 to completion. Benchmark: [source](https://gist.github.com/stjepang/023f5025623f5474184f9f4dfd6379ae) Improvement: ``` name old_ ns/iter new_ce_ ns/iter diff ns/iter diff % 1t 146,440 89,904 -56,536 -38.61% 2t 561,456 316,835 -244,621 -43.57% 4t 2,822,821 1,005,424 -1,817,397 -64.38% ``` r? @eddyb cc @alexcrichton @nagisa
This commit is contained in:
commit
2e4ab07fa0
|
@ -539,17 +539,16 @@ pub fn fetch_nand(&self, val: bool, order: Ordering) -> bool {
|
|||
// We can't use atomic_nand here because it can result in a bool with
|
||||
// an invalid value. This happens because the atomic operation is done
|
||||
// with an 8-bit integer internally, which would set the upper 7 bits.
|
||||
// So we just use a compare-exchange loop instead, which is what the
|
||||
// intrinsic actually expands to anyways on many platforms.
|
||||
let mut old = self.load(Relaxed);
|
||||
loop {
|
||||
let new = !(old && val);
|
||||
match self.compare_exchange_weak(old, new, order, Relaxed) {
|
||||
Ok(_) => break,
|
||||
Err(x) => old = x,
|
||||
}
|
||||
// So we just use fetch_xor or swap instead.
|
||||
if val {
|
||||
// !(x & true) == !x
|
||||
// We must invert the bool.
|
||||
self.fetch_xor(true, order)
|
||||
} else {
|
||||
// !(x & false) == true
|
||||
// We must set the bool to true.
|
||||
self.swap(true, order)
|
||||
}
|
||||
old
|
||||
}
|
||||
|
||||
/// Logical "or" with a boolean value.
|
||||
|
|
|
@ -24,10 +24,23 @@ fn bool_() {
|
|||
#[test]
|
||||
fn bool_and() {
|
||||
let a = AtomicBool::new(true);
|
||||
assert_eq!(a.fetch_and(false, SeqCst),true);
|
||||
assert_eq!(a.fetch_and(false, SeqCst), true);
|
||||
assert_eq!(a.load(SeqCst),false);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bool_nand() {
|
||||
let a = AtomicBool::new(false);
|
||||
assert_eq!(a.fetch_nand(false, SeqCst), false);
|
||||
assert_eq!(a.load(SeqCst), true);
|
||||
assert_eq!(a.fetch_nand(false, SeqCst), true);
|
||||
assert_eq!(a.load(SeqCst), true);
|
||||
assert_eq!(a.fetch_nand(true, SeqCst), true);
|
||||
assert_eq!(a.load(SeqCst), false);
|
||||
assert_eq!(a.fetch_nand(true, SeqCst), false);
|
||||
assert_eq!(a.load(SeqCst), true);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn uint_and() {
|
||||
let x = AtomicUsize::new(0xf731);
|
||||
|
|
Loading…
Reference in a new issue