Make Arc::make_unique check weak refs; add make_unique to Rc

This patch makes `Arc::make_unique` examine the number of weak
references as well as strong references, which is required for safety.

It also adds a `make_unique` method to the `Rc` type for consistency.

Closes #14521.
This commit is contained in:
Aaron Turon
2014-05-29 11:49:01 -07:00
parent 50b8528970
commit 7889c95124
2 changed files with 107 additions and 1 deletions

View File

@@ -152,7 +152,11 @@ impl<T: Send + Share + Clone> Arc<T> {
#[inline]
#[experimental]
pub fn make_unique<'a>(&'a mut self) -> &'a mut T {
if self.inner().strong.load(atomics::SeqCst) != 1 {
// Note that we hold a strong reference, which also counts as
// a weak reference, so we only clone if there is an
// additional reference of either kind.
if self.inner().strong.load(atomics::SeqCst) != 1 ||
self.inner().weak.load(atomics::SeqCst) != 1 {
*self = Arc::new(self.deref().clone())
}
// This unsafety is ok because we're guaranteed that the pointer
@@ -356,6 +360,20 @@ mod tests {
assert!(*cow1 == *cow2);
}
#[test]
fn test_cowarc_clone_weak() {
let mut cow0 = Arc::new(75u);
let cow1_weak = cow0.downgrade();
assert!(75 == *cow0);
assert!(75 == *cow1_weak.upgrade().unwrap());
*cow0.make_unique() += 1;
assert!(76 == *cow0);
assert!(cow1_weak.upgrade().is_none());
}
#[test]
fn test_live() {
let x = Arc::new(5);