|
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")]
|
@@ -82,7 +90,7 @@ impl OnceNonZeroUsize {
|
82 | 90 | #[inline]
|
83 | 91 | pub fn set(&self, value: NonZeroUsize) -> Result<(), ()> {
|
84 | 92 | let exchange =
|
85 |
| - self.inner.compare_exchange(0, value.get(), Ordering::AcqRel, Ordering::Acquire); |
| 93 | + self.inner.compare_exchange(0, value.get(), Ordering::Release, Ordering::Acquire); |
86 | 94 | match exchange {
|
87 | 95 | Ok(_) => Ok(()),
|
88 | 96 | Err(_) => Err(()),
|
@@ -128,7 +136,7 @@ impl OnceNonZeroUsize {
|
128 | 136 | #[inline(never)]
|
129 | 137 | fn init<E>(&self, f: impl FnOnce() -> Result<NonZeroUsize, E>) -> Result<NonZeroUsize, E> {
|
130 | 138 | let mut val = f()?.get();
|
131 |
| - let exchange = self.inner.compare_exchange(0, val, Ordering::AcqRel, Ordering::Acquire); |
| 139 | + let exchange = self.inner.compare_exchange(0, val, Ordering::Release, Ordering::Acquire); |
132 | 140 | if let Err(old) = exchange {
|
133 | 141 | val = old;
|
134 | 142 | }
|
@@ -242,7 +250,7 @@ impl<'a, T> OnceRef<'a, T> {
|
242 | 250 | pub fn set(&self, value: &'a T) -> Result<(), ()> {
|
243 | 251 | let ptr = value as *const T as *mut T;
|
244 | 252 | let exchange =
|
245 |
| - self.inner.compare_exchange(ptr::null_mut(), ptr, Ordering::AcqRel, Ordering::Acquire); |
| 253 | + self.inner.compare_exchange(ptr::null_mut(), ptr, Ordering::Release, Ordering::Acquire); |
246 | 254 | match exchange {
|
247 | 255 | Ok(_) => Ok(()),
|
248 | 256 | Err(_) => Err(()),
|
@@ -285,7 +293,7 @@ impl<'a, T> OnceRef<'a, T> {
|
285 | 293 | let exchange = self.inner.compare_exchange(
|
286 | 294 | ptr::null_mut(),
|
287 | 295 | ptr,
|
288 |
| - Ordering::AcqRel, |
| 296 | + Ordering::Release, |
289 | 297 | Ordering::Acquire,
|
290 | 298 | );
|
291 | 299 | if let Err(old) = exchange {
|
@@ -380,7 +388,7 @@ mod once_box {
|
380 | 388 | let exchange = self.inner.compare_exchange(
|
381 | 389 | ptr::null_mut(),
|
382 | 390 | ptr,
|
383 |
| - Ordering::AcqRel, |
| 391 | + Ordering::Release, |
384 | 392 | Ordering::Acquire,
|
385 | 393 | );
|
386 | 394 | if exchange.is_err() {
|
@@ -426,7 +434,7 @@ mod once_box {
|
426 | 434 | let exchange = self.inner.compare_exchange(
|
427 | 435 | ptr::null_mut(),
|
428 | 436 | ptr,
|
429 |
| - Ordering::AcqRel, |
| 437 | + Ordering::Release, |
430 | 438 | Ordering::Acquire,
|
431 | 439 | );
|
432 | 440 | if let Err(old) = exchange {
|
|
0 commit comments