about summary refs log tree commit diff
path: root/src/libcore/sync
diff options
context:
space:
mode:
authorStjepan Glavina <stjepang@gmail.com>2017-04-07 17:28:55 +0200
committerStjepan Glavina <stjepang@gmail.com>2017-04-07 17:36:50 +0200
commit5c5a5182c94d07409fac8cb40b2cdab488c140ff (patch)
tree26c8b3344ab5d7e448db21009d33c6e5ade7ff10 /src/libcore/sync
parent4c59c92bc4d4d6e5b2b66c4cc08dd1a058283a0d (diff)
downloadrust-5c5a5182c94d07409fac8cb40b2cdab488c140ff.tar.gz
rust-5c5a5182c94d07409fac8cb40b2cdab488c140ff.zip
Optimize AtomicBool::fetch_nand
Diffstat (limited to 'src/libcore/sync')
-rw-r--r--src/libcore/sync/atomic.rs22
1 files changed, 13 insertions, 9 deletions
diff --git a/src/libcore/sync/atomic.rs b/src/libcore/sync/atomic.rs
index 2e1058bfc34..dd0069502de 100644
--- a/src/libcore/sync/atomic.rs
+++ b/src/libcore/sync/atomic.rs
@@ -539,17 +539,21 @@ impl AtomicBool {
         // 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 compare_exchange 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. Instead of delegating to swap or fetch_or, use
+            // compare_exchange instead in order to avoid unnecessary writes to memory, which
+            // might minimize cache-coherence traffic.
+            match self.compare_exchange(false, true, order, Ordering::Relaxed) {
+                Ok(_) => false,
+                Err(_) => true,
             }
         }
-        old
     }
 
     /// Logical "or" with a boolean value.