mirror of
https://github.com/rust-lang/rust.git
synced 2025-05-14 02:49:40 +00:00
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
@ -1048,14 +1048,16 @@ impl<T: Clone> Rc<T> {
|
||||
}
|
||||
} else if Rc::weak_count(this) != 0 {
|
||||
// Can just steal the data, all that's left is Weaks
|
||||
let mut rc = Self::new_uninit();
|
||||
unsafe {
|
||||
let mut swap = Rc::new(ptr::read(&this.ptr.as_ref().value));
|
||||
mem::swap(this, &mut swap);
|
||||
swap.inner().dec_strong();
|
||||
let data = Rc::get_mut_unchecked(&mut rc);
|
||||
data.as_mut_ptr().copy_from_nonoverlapping(&**this, 1);
|
||||
|
||||
this.inner().dec_strong();
|
||||
// Remove implicit strong-weak ref (no need to craft a fake
|
||||
// Weak here -- we know other Weaks can clean up for us)
|
||||
swap.inner().dec_weak();
|
||||
forget(swap);
|
||||
this.inner().dec_weak();
|
||||
ptr::write(this, rc.assume_init());
|
||||
}
|
||||
}
|
||||
// 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
|
||||
// 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 {
|
||||
// there is no data race in the implicit write caused by `read`
|
||||
// here (due to zeroing) because data is no longer accessed by
|
||||
// other threads (due to there being no more strong refs at this
|
||||
// point).
|
||||
let mut swap = Arc::new(ptr::read(&weak.ptr.as_ref().data));
|
||||
mem::swap(this, &mut swap);
|
||||
mem::forget(swap);
|
||||
let data = Arc::get_mut_unchecked(&mut arc);
|
||||
data.as_mut_ptr().copy_from_nonoverlapping(&**this, 1);
|
||||
ptr::write(this, arc.assume_init());
|
||||
}
|
||||
} else {
|
||||
// We were the sole reference of either kind; bump back up the
|
||||
|
Loading…
Reference in New Issue
Block a user