Skip to content

Commit ead7a0b

Browse files
committed
Add {Rc, Arc}::make_mut_slice().
These functions behave identically to `make_mut()`, but operate on `Arc<[T]>` instead of `Arc<T>`.
1 parent ffc48e3 commit ead7a0b

File tree

2 files changed

+191
-0
lines changed

2 files changed

+191
-0
lines changed

library/alloc/src/rc.rs

+85
Original file line numberDiff line numberDiff line change
@@ -1773,6 +1773,91 @@ impl<T: Clone, A: Allocator + Clone> Rc<T, A> {
17731773
}
17741774
}
17751775

1776+
impl<T: Clone, A: Allocator + Clone> Rc<[T], A> {
1777+
/// Makes a mutable reference into the given `Rc<[T]>`.
1778+
///
1779+
/// This function has the same purpose and characteristics as [`make_mut`](Self::make_mut),
1780+
/// except that it applies to slices rather than [`Sized`] values.
1781+
///
1782+
/// # Examples
1783+
///
1784+
/// ```
1785+
/// #![feature(make_mut_slice)]
1786+
/// use std::rc::Rc;
1787+
///
1788+
/// let mut data: Rc<[i32]> = Rc::new([10, 20, 30]);
1789+
///
1790+
/// Rc::make_mut_slice(&mut data)[0] += 1; // Won't clone anything
1791+
/// let mut other_data = Rc::clone(&data); // Won't clone inner data
1792+
/// Rc::make_mut_slice(&mut data)[1] += 1; // Clones inner data
1793+
/// Rc::make_mut_slice(&mut data)[2] += 1; // Won't clone anything
1794+
/// Rc::make_mut_slice(&mut other_data)[0] *= 10; // Won't clone anything
1795+
///
1796+
/// // Now `data` and `other_data` point to different allocations.
1797+
/// assert_eq!(*data, [11, 21, 31]);
1798+
/// assert_eq!(*other_data, [110, 20, 30]);
1799+
/// ```
1800+
///
1801+
/// [`Weak`] pointers will be disassociated:
1802+
///
1803+
/// ```
1804+
/// #![feature(make_mut_slice)]
1805+
/// use std::rc::Rc;
1806+
///
1807+
/// let mut data: Rc<[i32]> = Rc::new([75]);
1808+
/// let weak = Rc::downgrade(&data);
1809+
///
1810+
/// assert!([75] == *data);
1811+
/// assert!([75] == *weak.upgrade().unwrap());
1812+
///
1813+
/// Rc::make_mut_slice(&mut data)[0] += 1;
1814+
///
1815+
/// assert!([76] == *data);
1816+
/// assert!(weak.upgrade().is_none());
1817+
/// ```
1818+
#[cfg(not(no_global_oom_handling))]
1819+
#[inline]
1820+
#[unstable(feature = "make_mut_slice", issue = "none")]
1821+
pub fn make_mut_slice(this: &mut Self) -> &mut [T] {
1822+
// This code is identical to `make_mut()` except that it clones len() items instead of 1.
1823+
1824+
let len = this.len();
1825+
1826+
if Rc::strong_count(this) != 1 {
1827+
// Gotta clone the data, there are other Rcs.
1828+
// Pre-allocate memory to allow writing the cloned value directly.
1829+
let mut rc = Self::new_uninit_slice_in(len, this.alloc.clone());
1830+
unsafe {
1831+
let data = Rc::get_mut_unchecked(&mut rc);
1832+
for i in 0..len {
1833+
this[i].write_clone_into_raw(data[i].as_mut_ptr());
1834+
}
1835+
*this = rc.assume_init();
1836+
}
1837+
} else if Rc::weak_count(this) != 0 {
1838+
// Can just steal the data, all that's left is Weaks
1839+
let mut rc = Self::new_uninit_slice_in(len, this.alloc.clone());
1840+
unsafe {
1841+
let data = Rc::get_mut_unchecked(&mut rc);
1842+
mem::MaybeUninit::slice_as_mut_ptr(data)
1843+
.copy_from_nonoverlapping(this.as_ptr(), len);
1844+
1845+
this.inner().dec_strong();
1846+
// Remove implicit strong-weak ref (no need to craft a fake
1847+
// Weak here -- we know other Weaks can clean up for us)
1848+
this.inner().dec_weak();
1849+
ptr::write(this, rc.assume_init());
1850+
}
1851+
}
1852+
// This unsafety is ok because we're guaranteed that the pointer
1853+
// returned is the *only* pointer that will ever be returned to T. Our
1854+
// reference count is guaranteed to be 1 at this point, and we required
1855+
// the `Rc<T>` itself to be `mut`, so we're returning the only possible
1856+
// reference to the allocation.
1857+
unsafe { &mut this.ptr.as_mut().value }
1858+
}
1859+
}
1860+
17761861
impl<A: Allocator + Clone> Rc<dyn Any, A> {
17771862
/// Attempt to downcast the `Rc<dyn Any>` to a concrete type.
17781863
///

library/alloc/src/sync.rs

+106
Original file line numberDiff line numberDiff line change
@@ -2198,6 +2198,112 @@ impl<T: Clone, A: Allocator + Clone> Arc<T, A> {
21982198
}
21992199
}
22002200

2201+
impl<T: Clone, A: Allocator + Clone> Arc<[T], A> {
2202+
/// Makes a mutable reference into the given `Arc<[T]>`.
2203+
///
2204+
/// This function has the same purpose and characteristics as [`make_mut`](Self::make_mut),
2205+
/// except that it applies to slices rather than [`Sized`] values.
2206+
///
2207+
/// # Examples
2208+
///
2209+
/// ```
2210+
/// #![feature(make_mut_slice)]
2211+
/// use std::sync::Arc;
2212+
///
2213+
/// let mut data: Arc<[i32]> = Rc::new([10, 20, 30]);
2214+
///
2215+
/// Arc::make_mut_slice(&mut data)[0] += 1; // Won't clone anything
2216+
/// let mut other_data = Arc::clone(&data); // Won't clone inner data
2217+
/// Arc::make_mut_slice(&mut data)[1] += 1; // Clones inner data
2218+
/// Arc::make_mut_slice(&mut data)[2] += 1; // Won't clone anything
2219+
/// Arc::make_mut_slice(&mut other_data)[0] *= 10; // Won't clone anything
2220+
///
2221+
/// // Now `data` and `other_data` point to different allocations.
2222+
/// assert_eq!(*data, [11, 21, 31]);
2223+
/// assert_eq!(*other_data, [110, 20, 30]);
2224+
/// ```
2225+
///
2226+
/// [`Weak`] pointers will be disassociated:
2227+
///
2228+
/// ```
2229+
/// #![feature(make_mut_slice)]
2230+
/// use std::sync::Arc;
2231+
///
2232+
/// let mut data: Arc<[i32]> = Arc::new([75]);
2233+
/// let weak = Arc::downgrade(&data);
2234+
///
2235+
/// assert!([75] == *data);
2236+
/// assert!([75] == *weak.upgrade().unwrap());
2237+
///
2238+
/// Arc::make_mut_slice(&mut data)[0] += 1;
2239+
///
2240+
/// assert!([76] == *data);
2241+
/// assert!(weak.upgrade().is_none());
2242+
/// ```
2243+
#[cfg(not(no_global_oom_handling))]
2244+
#[inline]
2245+
#[stable(feature = "arc_unique", since = "1.4.0")]
2246+
pub fn make_mut_slice(this: &mut Self) -> &mut [T] {
2247+
// This code is identical to `make_mut()` except that it clones len() items instead of 1.
2248+
2249+
let len = this.len();
2250+
2251+
// Note that we hold both a strong reference and a weak reference.
2252+
// Thus, releasing our strong reference only will not, by itself, cause
2253+
// the memory to be deallocated.
2254+
//
2255+
// Use Acquire to ensure that we see any writes to `weak` that happen
2256+
// before release writes (i.e., decrements) to `strong`. Since we hold a
2257+
// weak count, there's no chance the ArcInner itself could be
2258+
// deallocated.
2259+
if this.inner().strong.compare_exchange(1, 0, Acquire, Relaxed).is_err() {
2260+
// Another strong pointer exists, so we must clone.
2261+
// Pre-allocate memory to allow writing the cloned value directly.
2262+
let mut arc = Self::new_uninit_slice_in(len, this.alloc.clone());
2263+
unsafe {
2264+
let data = Arc::get_mut_unchecked(&mut arc);
2265+
for i in 0..len {
2266+
this[i].write_clone_into_raw(data[i].as_mut_ptr());
2267+
}
2268+
*this = arc.assume_init();
2269+
}
2270+
} else if this.inner().weak.load(Relaxed) != 1 {
2271+
// Relaxed suffices in the above because this is fundamentally an
2272+
// optimization: we are always racing with weak pointers being
2273+
// dropped. Worst case, we end up allocated a new Arc unnecessarily.
2274+
2275+
// We removed the last strong ref, but there are additional weak
2276+
// refs remaining. We'll move the contents to a new Arc, and
2277+
// invalidate the other weak refs.
2278+
2279+
// Note that it is not possible for the read of `weak` to yield
2280+
// usize::MAX (i.e., locked), since the weak count can only be
2281+
// locked by a thread with a strong reference.
2282+
2283+
// Materialize our own implicit weak pointer, so that it can clean
2284+
// up the ArcInner as needed.
2285+
let _weak = Weak { ptr: this.ptr, alloc: this.alloc.clone() };
2286+
2287+
// Can just steal the data, all that's left is Weaks
2288+
let mut arc = Self::new_uninit_slice_in(len, this.alloc.clone());
2289+
unsafe {
2290+
let data = Arc::get_mut_unchecked(&mut arc);
2291+
mem::MaybeUninit::slice_as_mut_ptr(data)
2292+
.copy_from_nonoverlapping(this.as_ptr(), len);
2293+
ptr::write(this, arc.assume_init());
2294+
}
2295+
} else {
2296+
// We were the sole reference of either kind; bump back up the
2297+
// strong ref count.
2298+
this.inner().strong.store(1, Release);
2299+
}
2300+
2301+
// As with `get_mut()`, the unsafety is ok because our reference was
2302+
// either unique to begin with, or became one upon cloning the contents.
2303+
unsafe { Self::get_mut_unchecked(this) }
2304+
}
2305+
}
2306+
22012307
impl<T: ?Sized, A: Allocator> Arc<T, A> {
22022308
/// Returns a mutable reference into the given `Arc`, if there are
22032309
/// no other `Arc` or [`Weak`] pointers to the same allocation.

0 commit comments

Comments
 (0)