|
19 | 19 | //! `Acquire` and `Release` have very little performance overhead on most
|
20 | 20 | //! architectures versus `Relaxed`.
|
21 | 21 |
|
| 22 | +// The "atomic orderings" section of the documentation above promises |
| 23 | +// "happens-before" semantics. This drives the choice of orderings in the uses |
| 24 | +// of `compare_exchange` below. On success, the value was zero/null, so there |
| 25 | +// was nothing to acquire (there is never any `Ordering::Release` store of 0). |
| 26 | +// On failure, the value was nonzero, so it was initialized previously (perhaps |
| 27 | +// on another thread) using `Ordering::Release`, so we must use |
| 28 | +// `Ordering::Acquire` to ensure that store "happens-before" this load. |
| 29 | + |
22 | 30 | #[cfg(not(feature = "portable-atomic"))]
|
23 | 31 | use core::sync::atomic;
|
24 | 32 | #[cfg(feature = "portable-atomic")]
|
@@ -98,7 +106,7 @@ impl OnceNonZeroUsize {
|
98 | 106 | #[inline]
|
99 | 107 | pub fn set(&self, value: NonZeroUsize) -> Result<(), ()> {
|
100 | 108 | let exchange =
|
101 |
| - self.inner.compare_exchange(0, value.get(), Ordering::AcqRel, Ordering::Acquire); |
| 109 | + self.inner.compare_exchange(0, value.get(), Ordering::Release, Ordering::Acquire); |
102 | 110 | match exchange {
|
103 | 111 | Ok(_) => Ok(()),
|
104 | 112 | Err(_) => Err(()),
|
@@ -144,7 +152,7 @@ impl OnceNonZeroUsize {
|
144 | 152 | #[inline(never)]
|
145 | 153 | fn init<E>(&self, f: impl FnOnce() -> Result<NonZeroUsize, E>) -> Result<NonZeroUsize, E> {
|
146 | 154 | let mut val = f()?.get();
|
147 |
| - let exchange = self.inner.compare_exchange(0, val, Ordering::AcqRel, Ordering::Acquire); |
| 155 | + let exchange = self.inner.compare_exchange(0, val, Ordering::Release, Ordering::Acquire); |
148 | 156 | if let Err(old) = exchange {
|
149 | 157 | val = old;
|
150 | 158 | }
|
@@ -258,7 +266,7 @@ impl<'a, T> OnceRef<'a, T> {
|
258 | 266 | pub fn set(&self, value: &'a T) -> Result<(), ()> {
|
259 | 267 | let ptr = value as *const T as *mut T;
|
260 | 268 | let exchange =
|
261 |
| - self.inner.compare_exchange(ptr::null_mut(), ptr, Ordering::AcqRel, Ordering::Acquire); |
| 269 | + self.inner.compare_exchange(ptr::null_mut(), ptr, Ordering::Release, Ordering::Acquire); |
262 | 270 | match exchange {
|
263 | 271 | Ok(_) => Ok(()),
|
264 | 272 | Err(_) => Err(()),
|
@@ -301,7 +309,7 @@ impl<'a, T> OnceRef<'a, T> {
|
301 | 309 | let exchange = self.inner.compare_exchange(
|
302 | 310 | ptr::null_mut(),
|
303 | 311 | ptr,
|
304 |
| - Ordering::AcqRel, |
| 312 | + Ordering::Release, |
305 | 313 | Ordering::Acquire,
|
306 | 314 | );
|
307 | 315 | if let Err(old) = exchange {
|
@@ -396,7 +404,7 @@ mod once_box {
|
396 | 404 | let exchange = self.inner.compare_exchange(
|
397 | 405 | ptr::null_mut(),
|
398 | 406 | ptr,
|
399 |
| - Ordering::AcqRel, |
| 407 | + Ordering::Release, |
400 | 408 | Ordering::Acquire,
|
401 | 409 | );
|
402 | 410 | if exchange.is_err() {
|
@@ -442,7 +450,7 @@ mod once_box {
|
442 | 450 | let exchange = self.inner.compare_exchange(
|
443 | 451 | ptr::null_mut(),
|
444 | 452 | ptr,
|
445 |
| - Ordering::AcqRel, |
| 453 | + Ordering::Release, |
446 | 454 | Ordering::Acquire,
|
447 | 455 | );
|
448 | 456 | if let Err(old) = exchange {
|
|
0 commit comments