Skip to content

Commit 17d4a9b

Browse files
committed
DRY race::OnceRef::{get_or_try_init, set}.
Centralize all the pointer type casting and RMW into a new `compare_exchange` function as was done in other types in the module. Leave the dereferencing of the pointer in `init()` as `set()` doesn't ever use the old value.
1 parent 01b1d56 commit 17d4a9b

File tree

1 file changed

+17
-15
lines changed

1 file changed

+17
-15
lines changed

src/race.rs

+17-15
Original file line numberDiff line numberDiff line change
@@ -266,10 +266,7 @@ impl<'a, T> OnceRef<'a, T> {
266266
/// Returns `Ok(())` if the cell was empty and `Err(value)` if it was
267267
/// full.
268268
pub fn set(&self, value: &'a T) -> Result<(), ()> {
269-
let ptr = <*const T>::cast_mut(value);
270-
let exchange =
271-
self.inner.compare_exchange(ptr::null_mut(), ptr, Ordering::Release, Ordering::Acquire);
272-
match exchange {
269+
match self.compare_exchange(value) {
273270
Ok(_) => Ok(()),
274271
Err(_) => Err(()),
275272
}
@@ -312,19 +309,24 @@ impl<'a, T> OnceRef<'a, T> {
312309
#[cold]
313310
#[inline(never)]
314311
fn init<E>(&self, f: impl FnOnce() -> Result<&'a T, E>) -> Result<&'a T, E> {
315-
let value: &'a T = f()?;
316-
let mut ptr = <*const T>::cast_mut(value);
317-
let exchange = self.inner.compare_exchange(
318-
ptr::null_mut(),
319-
ptr,
320-
Ordering::Release,
321-
Ordering::Acquire,
322-
);
323-
if let Err(old) = exchange {
324-
ptr = old;
312+
let mut value: &'a T = f()?;
313+
if let Err(old) = self.compare_exchange(value) {
314+
value = unsafe { &*old };
325315
}
316+
Ok(value)
317+
}
326318

327-
Ok(unsafe { &*ptr })
319+
#[inline(always)]
320+
fn compare_exchange(&self, value: &'a T) -> Result<(), *const T> {
321+
self.inner
322+
.compare_exchange(
323+
ptr::null_mut(),
324+
<*const T>::cast_mut(value),
325+
Ordering::Release,
326+
Ordering::Acquire,
327+
)
328+
.map(|_: *mut T| ())
329+
.map_err(<*mut T>::cast_const)
328330
}
329331

330332
/// ```compile_fail

0 commit comments

Comments
 (0)