Move directly when Rc/Arc::make_mut splits from Weak
When only other `Weak` references remain, we can directly move the data into the new unique allocation as a plain memory copy.
This commit is contained in:
parent
d85df44e8d
commit
f89f30fb2c
2 changed files with 13 additions and 14 deletions
|
@ -1048,14 +1048,16 @@ impl<T: Clone> Rc<T> {
|
||||||
}
|
}
|
||||||
} else if Rc::weak_count(this) != 0 {
|
} else if Rc::weak_count(this) != 0 {
|
||||||
// Can just steal the data, all that's left is Weaks
|
// Can just steal the data, all that's left is Weaks
|
||||||
|
let mut rc = Self::new_uninit();
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut swap = Rc::new(ptr::read(&this.ptr.as_ref().value));
|
let data = Rc::get_mut_unchecked(&mut rc);
|
||||||
mem::swap(this, &mut swap);
|
data.as_mut_ptr().copy_from_nonoverlapping(&**this, 1);
|
||||||
swap.inner().dec_strong();
|
|
||||||
|
this.inner().dec_strong();
|
||||||
// Remove implicit strong-weak ref (no need to craft a fake
|
// Remove implicit strong-weak ref (no need to craft a fake
|
||||||
// Weak here -- we know other Weaks can clean up for us)
|
// Weak here -- we know other Weaks can clean up for us)
|
||||||
swap.inner().dec_weak();
|
this.inner().dec_weak();
|
||||||
forget(swap);
|
ptr::write(this, rc.assume_init());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// This unsafety is ok because we're guaranteed that the pointer
|
// This unsafety is ok because we're guaranteed that the pointer
|
||||||
|
|
|
@ -1392,17 +1392,14 @@ impl<T: Clone> Arc<T> {
|
||||||
|
|
||||||
// Materialize our own implicit weak pointer, so that it can clean
|
// Materialize our own implicit weak pointer, so that it can clean
|
||||||
// up the ArcInner as needed.
|
// up the ArcInner as needed.
|
||||||
let weak = Weak { ptr: this.ptr };
|
let _weak = Weak { ptr: this.ptr };
|
||||||
|
|
||||||
// mark the data itself as already deallocated
|
// Can just steal the data, all that's left is Weaks
|
||||||
|
let mut arc = Self::new_uninit();
|
||||||
unsafe {
|
unsafe {
|
||||||
// there is no data race in the implicit write caused by `read`
|
let data = Arc::get_mut_unchecked(&mut arc);
|
||||||
// here (due to zeroing) because data is no longer accessed by
|
data.as_mut_ptr().copy_from_nonoverlapping(&**this, 1);
|
||||||
// other threads (due to there being no more strong refs at this
|
ptr::write(this, arc.assume_init());
|
||||||
// point).
|
|
||||||
let mut swap = Arc::new(ptr::read(&weak.ptr.as_ref().data));
|
|
||||||
mem::swap(this, &mut swap);
|
|
||||||
mem::forget(swap);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// We were the sole reference of either kind; bump back up the
|
// We were the sole reference of either kind; bump back up the
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue