Skip to content

Commit e94df55

Browse files
authored
Merge pull request #195 from 0xfMel/master
Fix Debt::pay failure ordering
2 parents 22431da + bd5d327 commit e94df55

1 file changed

Lines changed: 8 additions & 7 deletions

File tree

src/debt/mod.rs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -64,16 +64,17 @@ impl Debt {
6464
#[inline]
6565
pub(crate) fn pay<T: RefCnt>(&self, ptr: *const T::Base) -> bool {
6666
self.0
67-
// If we don't change anything because there's something else, Relaxed is fine.
67+
// On failure, we have observed that the debt has been paid, but we need to establish a
68+
// happens-before relationship with that debt being paid before we do anything that
69+
// relies on the Arc's strong counter being incremented, so we need to Acquire.
70+
// Arc does not sufficiently take care of this, as the memory model permits its Drop's
71+
// `fetch_sub` to observe itself to be last remaining instance before the `fetch_add`s
72+
// from the debt being repaid, and only after that observation does Arc have an Acquire
73+
// fence.
6874
//
6975
// The Release works as kind of Mutex. We make sure nothing from the debt-protected
7076
// sections leaks below this point.
71-
//
72-
// Note that if it got paid already, it is inside the reference count. We don't
73-
// necessarily observe that increment, but whoever destroys the pointer *must* see the
74-
// up to date value, with all increments already counted in (the Arc takes care of that
75-
// part).
76-
.compare_exchange(ptr as usize, Self::NONE, Release, Relaxed)
77+
.compare_exchange(ptr as usize, Self::NONE, Release, Acquire)
7778
.is_ok()
7879
}
7980

0 commit comments

Comments
 (0)