Skip to content

Commit

Permalink
Relax memory ordering in AtomicCell::replace (#83)
Browse files Browse the repository at this point in the history
  • Loading branch information
taiki-e authored Sep 10, 2023
1 parent 450942e commit 7bbabd0
Showing 1 changed file with 10 additions and 2 deletions.
12 changes: 10 additions & 2 deletions src/no_std/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -218,12 +218,20 @@ impl<T> AtomicCell<T> {

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

if old_value.is_null() {
None
} else {
// SAFETY:
// - AcqRel/Acquire ensures that it does not read a pointer to potentially invalid memory.
// - We've checked that old_value is not null.
// - We do not store invalid pointers other than null in self.0.
Some(unsafe { Box::from_raw(old_value) })
}
}
Expand Down

0 comments on commit 7bbabd0

Please sign in to comment.