Skip to content

Commit 80c8680

Browse files
Use fetch_update in sync::Weak::upgrade
1 parent cba4a38 commit 80c8680

File tree

1 file changed

+16
-23
lines changed

1 file changed

+16
-23
lines changed

library/alloc/src/sync.rs

+16-23
Original file line numberDiff line numberDiff line change
@@ -1980,33 +1980,26 @@ impl<T: ?Sized> Weak<T> {
19801980
// We use a CAS loop to increment the strong count instead of a
19811981
// fetch_add as this function should never take the reference count
19821982
// from zero to one.
1983-
let inner = self.inner()?;
1984-
1985-
// Relaxed load because any write of 0 that we can observe
1986-
// leaves the field in a permanently zero state (so a
1987-
// "stale" read of 0 is fine), and any other value is
1988-
// confirmed via the CAS below.
1989-
let mut n = inner.strong.load(Relaxed);
1990-
1991-
loop {
1992-
if n == 0 {
1993-
return None;
1994-
}
1995-
1996-
// See comments in `Arc::clone` for why we do this (for `mem::forget`).
1997-
if n > MAX_REFCOUNT {
1998-
abort();
1999-
}
2000-
1983+
self.inner()?
1984+
.strong
20011985
// Relaxed is fine for the failure case because we don't have any expectations about the new state.
20021986
// Acquire is necessary for the success case to synchronise with `Arc::new_cyclic`, when the inner
20031987
// value can be initialized after `Weak` references have already been created. In that case, we
20041988
// expect to observe the fully initialized value.
2005-
match inner.strong.compare_exchange_weak(n, n + 1, Acquire, Relaxed) {
2006-
Ok(_) => return Some(unsafe { Arc::from_inner(self.ptr) }), // null checked above
2007-
Err(old) => n = old,
2008-
}
2009-
}
1989+
.fetch_update(Acquire, Relaxed, |n| {
1990+
// Any write of 0 we can observe leaves the field in permanently zero state.
1991+
if n == 0 {
1992+
return None;
1993+
}
1994+
// See comments in `Arc::clone` for why we do this (for `mem::forget`).
1995+
if n > MAX_REFCOUNT {
1996+
abort();
1997+
}
1998+
Some(n + 1)
1999+
})
2000+
.ok()
2001+
// null checked above
2002+
.map(|_| unsafe { Arc::from_inner(self.ptr) })
20102003
}
20112004

20122005
/// Gets the number of strong (`Arc`) pointers pointing to this allocation.

0 commit comments

Comments
 (0)