Understanding happens-before relationship in this case

Acquire loading a particular value which was stored by a Release operation helps in establishing a happens-before relationship, but how exactly does this work? Does the fence create like a wait point, where it waits for all operations on the shared memory to finish after which we could finally drop the shared memory?

impl<T> Drop for Arc<T> {
    fn drop(&mut self) {
        if self.data().ref_count.fetch_sub(1, Release) == 1 {
            fence(Acquire);
            unsafe {
                drop(Box::from_raw(self.ptr.as_ptr()));
            }
        }
    }
}

This comment in std covers it:

This fence is needed to prevent reordering of use of the data and deletion of the data. Because it is marked Release, the decreasing of the reference count synchronizes with this Acquire fence. This means that use of the data happens before decreasing the reference count, which happens before this fence, which happens before the deletion of the data.

1 Like