diff --git a/src/libcore/sync/atomic.rs b/src/libcore/sync/atomic.rs index 743e3c41170a3..106b7183bd4ed 100644 --- a/src/libcore/sync/atomic.rs +++ b/src/libcore/sync/atomic.rs @@ -512,17 +512,26 @@ 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 simplify to fetch_xor or a swap. + + // !(true && true) == false + // !(true && false) == true + // !(false && false) == true + // !(false && true) == true + + // !(x && true) == !x + // !(x && false) == true + if val { + return self.fetch_xor(true, order); + } else { + // Use a compare exchange instead of a swap because it + // avoids a write in some cases which is good for caches. + match self.compare_exchange(false, true, order, + Ordering::Relaxed) { + Ok(_) => false, + Err(_) => true } } - old } /// Logical "or" with a boolean value.