From 7ec216c4607a53b2da7151563d000619b860abc9 Mon Sep 17 00:00:00 2001 From: Steven Stewart-Gallus Date: Wed, 15 Mar 2017 17:52:35 -0700 Subject: [PATCH 1/2] Simplify AtomicBool::fetch_nand This should also be faster --- src/libcore/sync/atomic.rs | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/src/libcore/sync/atomic.rs b/src/libcore/sync/atomic.rs index 743e3c41170a3..adcccb2c66c76 100644 --- a/src/libcore/sync/atomic.rs +++ b/src/libcore/sync/atomic.rs @@ -512,17 +512,24 @@ 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 + // So we just use a compare-exchange 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, + + // !(true && true) == false + // !(false && false) == true + if val { + match self.compare_exchange(true, false, order, + Ordering::Relaxed) { + Ok(_) => true, + Err(_) => false + } + } else { + match self.compare_exchange(false, true, order, + Ordering::Relaxed) { + Ok(_) => false, + Err(_) => true } } - old } /// Logical "or" with a boolean value. From 340351049695388670ae459891ce007836548dee Mon Sep 17 00:00:00 2001 From: Steven Stewart-Gallus Date: Mon, 20 Mar 2017 14:45:13 -0700 Subject: [PATCH 2/2] Fix breaking test --- src/libcore/sync/atomic.rs | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/libcore/sync/atomic.rs b/src/libcore/sync/atomic.rs index adcccb2c66c76..106b7183bd4ed 100644 --- a/src/libcore/sync/atomic.rs +++ b/src/libcore/sync/atomic.rs @@ -512,18 +512,20 @@ 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 instead, which is what the - // intrinsic actually expands to anyways on many platforms. + // 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 { - match self.compare_exchange(true, false, order, - Ordering::Relaxed) { - Ok(_) => true, - Err(_) => false - } + 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,