Skip to content

Commit 2e4ab07

Browse files
authored
Rollup merge of rust-lang#41143 - stjepang:optimize-bool-fetch-nand, r=nagisa
Optimize AtomicBool::fetch_nand This is an attempt to push the PR rust-lang#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
2 parents 29880e6 + f7ffe5b commit 2e4ab07

File tree

2 files changed

+23
-11
lines changed

2 files changed

+23
-11
lines changed

src/libcore/sync/atomic.rs

+9-10
Original file line numberDiff line numberDiff line change
@@ -539,17 +539,16 @@ impl AtomicBool {
539539
// We can't use atomic_nand here because it can result in a bool with
540540
// an invalid value. This happens because the atomic operation is done
541541
// with an 8-bit integer internally, which would set the upper 7 bits.
542-
// So we just use a compare-exchange loop instead, which is what the
543-
// intrinsic actually expands to anyways on many platforms.
544-
let mut old = self.load(Relaxed);
545-
loop {
546-
let new = !(old && val);
547-
match self.compare_exchange_weak(old, new, order, Relaxed) {
548-
Ok(_) => break,
549-
Err(x) => old = x,
550-
}
542+
// So we just use fetch_xor or swap instead.
543+
if val {
544+
// !(x & true) == !x
545+
// We must invert the bool.
546+
self.fetch_xor(true, order)
547+
} else {
548+
// !(x & false) == true
549+
// We must set the bool to true.
550+
self.swap(true, order)
551551
}
552-
old
553552
}
554553

555554
/// Logical "or" with a boolean value.

src/libcore/tests/atomic.rs

+14-1
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,23 @@ fn bool_() {
2424
#[test]
2525
fn bool_and() {
2626
let a = AtomicBool::new(true);
27-
assert_eq!(a.fetch_and(false, SeqCst),true);
27+
assert_eq!(a.fetch_and(false, SeqCst), true);
2828
assert_eq!(a.load(SeqCst),false);
2929
}
3030

31+
#[test]
32+
fn bool_nand() {
33+
let a = AtomicBool::new(false);
34+
assert_eq!(a.fetch_nand(false, SeqCst), false);
35+
assert_eq!(a.load(SeqCst), true);
36+
assert_eq!(a.fetch_nand(false, SeqCst), true);
37+
assert_eq!(a.load(SeqCst), true);
38+
assert_eq!(a.fetch_nand(true, SeqCst), true);
39+
assert_eq!(a.load(SeqCst), false);
40+
assert_eq!(a.fetch_nand(true, SeqCst), false);
41+
assert_eq!(a.load(SeqCst), true);
42+
}
43+
3144
#[test]
3245
fn uint_and() {
3346
let x = AtomicUsize::new(0xf731);

0 commit comments

Comments
 (0)