diff options
| author | Tim Neumann <mail@timnn.me> | 2017-04-08 08:55:09 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2017-04-08 08:55:09 +0200 |
| commit | 2e4ab07fa0c291347382832eec9d292fcdcc8b8d (patch) | |
| tree | 9535acab1622caff62518333692a08eee7cff53a /src | |
| parent | 29880e678f0ae5b0e83e51bf68d93229beb61ec9 (diff) | |
| parent | f7ffe5bd2499663026787f91f60e3e3ecf946a03 (diff) | |
| download | rust-2e4ab07fa0c291347382832eec9d292fcdcc8b8d.tar.gz rust-2e4ab07fa0c291347382832eec9d292fcdcc8b8d.zip | |
Rollup merge of #41143 - stjepang:optimize-bool-fetch-nand, r=nagisa
Optimize AtomicBool::fetch_nand This is an attempt to push the PR #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
Diffstat (limited to 'src')
| -rw-r--r-- | src/libcore/sync/atomic.rs | 19 | ||||
| -rw-r--r-- | src/libcore/tests/atomic.rs | 15 |
2 files changed, 23 insertions, 11 deletions
diff --git a/src/libcore/sync/atomic.rs b/src/libcore/sync/atomic.rs index 2e1058bfc34..a4050f271eb 100644 --- a/src/libcore/sync/atomic.rs +++ b/src/libcore/sync/atomic.rs @@ -539,17 +539,16 @@ 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 swap 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. + self.swap(true, order) } - old } /// Logical "or" with a boolean value. diff --git a/src/libcore/tests/atomic.rs b/src/libcore/tests/atomic.rs index b6bb5fddf4a..9babe24a985 100644 --- a/src/libcore/tests/atomic.rs +++ b/src/libcore/tests/atomic.rs @@ -24,11 +24,24 @@ fn bool_() { #[test] fn bool_and() { let a = AtomicBool::new(true); - assert_eq!(a.fetch_and(false, SeqCst),true); + assert_eq!(a.fetch_and(false, SeqCst), true); assert_eq!(a.load(SeqCst),false); } #[test] +fn bool_nand() { + let a = AtomicBool::new(false); + assert_eq!(a.fetch_nand(false, SeqCst), false); + assert_eq!(a.load(SeqCst), true); + assert_eq!(a.fetch_nand(false, SeqCst), true); + assert_eq!(a.load(SeqCst), true); + assert_eq!(a.fetch_nand(true, SeqCst), true); + assert_eq!(a.load(SeqCst), false); + assert_eq!(a.fetch_nand(true, SeqCst), false); + assert_eq!(a.load(SeqCst), true); +} + +#[test] fn uint_and() { let x = AtomicUsize::new(0xf731); assert_eq!(x.fetch_and(0x137f, SeqCst), 0xf731); |
