File tree 2 files changed +27
-10
lines changed
2 files changed +27
-10
lines changed Original file line number Diff line number Diff line change @@ -539,17 +539,21 @@ impl AtomicBool {
539
539
// We can't use atomic_nand here because it can result in a bool with
540
540
// an invalid value. This happens because the atomic operation is done
541
541
// 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,
542
+ // So we just use fetch_xor or compare_exchange 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. Instead of delegating to swap or fetch_or, use
550
+ // compare_exchange instead in order to avoid unnecessary writes to memory, which
551
+ // might minimize cache-coherence traffic.
552
+ match self . compare_exchange ( false , true , order, Ordering :: Relaxed ) {
553
+ Ok ( _) => false ,
554
+ Err ( _) => true ,
550
555
}
551
556
}
552
- old
553
557
}
554
558
555
559
/// Logical "or" with a boolean value.
Original file line number Diff line number Diff line change @@ -24,10 +24,23 @@ fn bool_() {
24
24
#[ test]
25
25
fn bool_and ( ) {
26
26
let a = AtomicBool :: new ( true ) ;
27
- assert_eq ! ( a. fetch_and( false , SeqCst ) , true ) ;
27
+ assert_eq ! ( a. fetch_and( false , SeqCst ) , true ) ;
28
28
assert_eq ! ( a. load( SeqCst ) , false ) ;
29
29
}
30
30
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
+
31
44
#[ test]
32
45
fn uint_and ( ) {
33
46
let x = AtomicUsize :: new ( 0xf731 ) ;
You can’t perform that action at this time.
0 commit comments