Skip to content

Commit 7a310c6

Browse files
authored
Merge pull request #278 from briansmith/b/weaken-release
race: Relax success ordering from `AcqRel` to `Release`.
2 parents a70d907 + 2a707ee commit 7a310c6

File tree

4 files changed

+19
-8
lines changed

4 files changed

+19
-8
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
# Changelog
22

3+
## 1.21.2
4+
- Relax success ordering from AcqRel to Release in `race`: [#278](https://github.com/matklad/once_cell/pull/278).
5+
36
## 1.21.1
47
- Reduce MSRV to 1.65: [#277](https://github.com/matklad/once_cell/pull/277).
58

Cargo.lock.msrv

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "once_cell"
3-
version = "1.21.1"
3+
version = "1.21.2"
44
authors = ["Aleksey Kladov <aleksey.kladov@gmail.com>"]
55
license = "MIT OR Apache-2.0"
66
edition = "2021"

src/race.rs

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,14 @@
1919
//! `Acquire` and `Release` have very little performance overhead on most
2020
//! architectures versus `Relaxed`.
2121
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+
2230
#[cfg(not(feature = "portable-atomic"))]
2331
use core::sync::atomic;
2432
#[cfg(feature = "portable-atomic")]
@@ -98,7 +106,7 @@ impl OnceNonZeroUsize {
98106
#[inline]
99107
pub fn set(&self, value: NonZeroUsize) -> Result<(), ()> {
100108
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);
102110
match exchange {
103111
Ok(_) => Ok(()),
104112
Err(_) => Err(()),
@@ -144,7 +152,7 @@ impl OnceNonZeroUsize {
144152
#[inline(never)]
145153
fn init<E>(&self, f: impl FnOnce() -> Result<NonZeroUsize, E>) -> Result<NonZeroUsize, E> {
146154
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);
148156
if let Err(old) = exchange {
149157
val = old;
150158
}
@@ -258,7 +266,7 @@ impl<'a, T> OnceRef<'a, T> {
258266
pub fn set(&self, value: &'a T) -> Result<(), ()> {
259267
let ptr = value as *const T as *mut T;
260268
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);
262270
match exchange {
263271
Ok(_) => Ok(()),
264272
Err(_) => Err(()),
@@ -301,7 +309,7 @@ impl<'a, T> OnceRef<'a, T> {
301309
let exchange = self.inner.compare_exchange(
302310
ptr::null_mut(),
303311
ptr,
304-
Ordering::AcqRel,
312+
Ordering::Release,
305313
Ordering::Acquire,
306314
);
307315
if let Err(old) = exchange {
@@ -396,7 +404,7 @@ mod once_box {
396404
let exchange = self.inner.compare_exchange(
397405
ptr::null_mut(),
398406
ptr,
399-
Ordering::AcqRel,
407+
Ordering::Release,
400408
Ordering::Acquire,
401409
);
402410
if exchange.is_err() {
@@ -442,7 +450,7 @@ mod once_box {
442450
let exchange = self.inner.compare_exchange(
443451
ptr::null_mut(),
444452
ptr,
445-
Ordering::AcqRel,
453+
Ordering::Release,
446454
Ordering::Acquire,
447455
);
448456
if let Err(old) = exchange {

0 commit comments

Comments
 (0)