Skip to content

Commit 7bbabd0

Browse files
authored
Relax memory ordering in AtomicCell::replace (#83)
1 parent 450942e commit 7bbabd0

File tree

1 file changed

+10
-2
lines changed

1 file changed

+10
-2
lines changed

src/no_std/node.rs

+10-2
Original file line numberDiff line numberDiff line change
@@ -218,12 +218,20 @@ impl<T> AtomicCell<T> {
218218

219219
/// Swap the value out.
220220
fn replace(&self, value: Option<Box<T>>) -> Option<Box<T>> {
221-
let value = value.map_or(ptr::null_mut(), |value| Box::into_raw(value));
222-
let old_value = self.0.swap(value, Ordering::SeqCst);
221+
let old_value = match value {
222+
Some(value) => self.0.swap(Box::into_raw(value), Ordering::AcqRel),
223+
// Acquire is needed to synchronize with the store of a non-null ptr, but since a null ptr
224+
// will never be dereferenced, there is no need to synchronize the store of a null ptr.
225+
None => self.0.swap(ptr::null_mut(), Ordering::Acquire),
226+
};
223227

224228
if old_value.is_null() {
225229
None
226230
} else {
231+
// SAFETY:
232+
// - AcqRel/Acquire ensures that it does not read a pointer to potentially invalid memory.
233+
// - We've checked that old_value is not null.
234+
// - We do not store invalid pointers other than null in self.0.
227235
Some(unsafe { Box::from_raw(old_value) })
228236
}
229237
}

0 commit comments

Comments
 (0)