Skip to main content

triomphe/
unique_arc.rs

1use alloc::vec::Vec;
2use alloc::{alloc::Layout, boxed::Box};
3use core::convert::TryFrom;
4use core::iter::FromIterator;
5use core::marker::PhantomData;
6use core::mem::{self, ManuallyDrop, MaybeUninit};
7use core::ops::{Deref, DerefMut};
8use core::ptr::{self, addr_of_mut};
9
10#[cfg(feature = "serde")]
11use serde::{Deserialize, Serialize};
12
13use crate::iterator_as_exact_size_iterator::IteratorAsExactSizeIterator;
14use crate::{mdref, AllocError, HeaderSlice};
15
16use super::{Arc, ArcInner};
17
18/// An `Arc` that is known to be uniquely owned
19///
20/// When `Arc`s are constructed, they are known to be
21/// uniquely owned. In such a case it is safe to mutate
22/// the contents of the `Arc`. Normally, one would just handle
23/// this by mutating the data on the stack before allocating the
24/// `Arc`, however it's possible the data is large or unsized
25/// and you need to heap-allocate it earlier in such a way
26/// that it can be freely converted into a regular `Arc` once you're
27/// done.
28///
29/// `UniqueArc` exists for this purpose, when constructed it performs
30/// the same allocations necessary for an `Arc`, however it allows mutable access.
31/// Once the mutation is finished, you can call `.shareable()` and get a regular `Arc`
32/// out of it.
33///
34/// ```rust
35/// # use triomphe::UniqueArc;
36/// let data = [1, 2, 3, 4, 5];
37/// let mut x = UniqueArc::new(data);
38/// x[4] = 7; // mutate!
39/// let y = x.shareable(); // y is an Arc<T>
40/// ```
41#[repr(transparent)]
42pub struct UniqueArc<T: ?Sized>(Arc<T>);
43
44// Uniquene ownership means that we can support weaker bounds than `T: Send + Sync`.
45// Thus, these impls can follow the precedent of std's `Box`, not `Arc`.
46unsafe impl<T: ?Sized + Send> Send for UniqueArc<T> {}
47unsafe impl<T: ?Sized + Sync> Sync for UniqueArc<T> {}
48
49impl<T> UniqueArc<T> {
50    #[inline]
51    /// Construct a new UniqueArc
52    pub fn new(data: T) -> Self {
53        UniqueArc(Arc::new(data))
54    }
55
56    /// Fallible version of [`UniqueArc::new`].
57    ///
58    /// Returns `Err(AllocError)` instead of aborting on allocation failure.
59    #[inline]
60    pub fn try_new(data: T) -> Result<Self, AllocError> {
61        Arc::try_new(data).map(UniqueArc)
62    }
63
64    /// Construct an uninitialized arc
65    #[inline]
66    pub fn new_uninit() -> UniqueArc<MaybeUninit<T>> {
67        // Delegate to the shared `Arc` allocation helper so that there is a
68        // single out-of-memory code path in the crate.
69        //
70        // Safety: the closure only changes the type of the pointer.
71        let inner = unsafe {
72            Arc::<MaybeUninit<T>>::allocate_for_layout(Layout::new::<MaybeUninit<T>>(), |mem| {
73                mem as *mut ArcInner<MaybeUninit<T>>
74            })
75        };
76
77        UniqueArc(Arc {
78            p: inner,
79            phantom: PhantomData,
80        })
81    }
82
83    /// Fallible version of [`UniqueArc::new_uninit`].
84    ///
85    /// Returns `Err(AllocError)` instead of aborting on allocation failure.
86    #[inline]
87    pub fn try_new_uninit() -> Result<UniqueArc<MaybeUninit<T>>, AllocError> {
88        // Safety: the closure only changes the type of the pointer.
89        let inner = unsafe {
90            Arc::<MaybeUninit<T>>::try_allocate_for_layout(
91                Layout::new::<MaybeUninit<T>>(),
92                |mem| mem as *mut ArcInner<MaybeUninit<T>>,
93            )?
94        };
95
96        Ok(UniqueArc(Arc {
97            p: inner,
98            phantom: PhantomData,
99        }))
100    }
101
102    /// Gets the inner value of the unique arc
103    pub fn into_inner(this: Self) -> T {
104        // Wrap the Arc in a `ManuallyDrop` so that its drop routine never runs
105        let this = ManuallyDrop::new(this.0);
106        debug_assert!(
107            this.is_unique(),
108            "attempted to call `.into_inner()` on a `UniqueArc` with a non-zero ref count",
109        );
110
111        // Safety: We have exclusive access to the inner data and the
112        //         arc will not perform its drop routine since we've
113        //         wrapped it in a `ManuallyDrop`
114        unsafe { Box::from_raw(this.ptr()).data }
115    }
116}
117
118impl<T: ?Sized> UniqueArc<T> {
119    /// Convert to a shareable `Arc<T>` once we're done mutating it
120    #[inline]
121    pub const fn shareable(self) -> Arc<T> {
122        let this = ManuallyDrop::new(self);
123        // Safety: UniqueArc isn't drop, just the inner Arc is
124        unsafe { mem::transmute_copy(&mdref(&this).0) }
125    }
126
127    /// Creates a new [`UniqueArc`] from the given [`Arc`].
128    ///
129    /// An unchecked alternative to `Arc::try_unique()`
130    ///
131    /// # Safety
132    ///
133    /// The given `Arc` must have a reference count of exactly one
134    ///
135    pub(crate) unsafe fn from_arc(arc: Arc<T>) -> Self {
136        debug_assert_eq!(Arc::count(&arc), 1);
137        Self(arc)
138    }
139
140    /// Creates a new `&mut `[`UniqueArc`] from the given `&mut `[`Arc`].
141    ///
142    /// An unchecked alternative to `Arc::try_as_unique()`
143    ///
144    /// # Safety
145    ///
146    /// The given `Arc` must have a reference count of exactly one
147    pub(crate) unsafe fn from_arc_ref(arc: &mut Arc<T>) -> &mut Self {
148        debug_assert_eq!(Arc::count(arc), 1);
149
150        // Safety: caller guarantees that `arc` is unique,
151        //         `UniqueArc` is `repr(transparent)`
152        &mut *(arc as *mut Arc<T> as *mut UniqueArc<T>)
153    }
154}
155
156impl<T> UniqueArc<MaybeUninit<T>> {
157    /// Calls `MaybeUninit::write` on the contained value.
158    pub fn write(&mut self, val: T) -> &mut T {
159        unsafe {
160            // Casting *mut MaybeUninit<T> -> *mut T is always fine
161            let ptr = self.as_mut_ptr() as *mut T;
162
163            // Safety: We have exclusive access to the inner data
164            ptr.write(val);
165
166            // Safety: the pointer was just written to
167            &mut *ptr
168        }
169    }
170
171    /// Obtain a mutable pointer to the stored `MaybeUninit<T>`.
172    pub const fn as_mut_ptr(&mut self) -> *mut MaybeUninit<T> {
173        unsafe { addr_of_mut!((*self.0.ptr()).data) }
174    }
175
176    /// Convert to an initialized Arc.
177    ///
178    /// # Safety
179    ///
180    /// This function is equivalent to `MaybeUninit::assume_init` and has the
181    /// same safety requirements. You are responsible for ensuring that the `T`
182    /// has actually been initialized before calling this method.
183    #[inline]
184    pub const unsafe fn assume_init(this: Self) -> UniqueArc<T> {
185        let this = ManuallyDrop::new(this);
186        UniqueArc(Arc {
187            p: mdref(&this).0.p.cast(),
188            phantom: PhantomData,
189        })
190    }
191}
192
193impl<T> UniqueArc<[MaybeUninit<T>]> {
194    /// Create an Arc contains an array `[MaybeUninit<T>]` of `len`.
195    pub fn new_uninit_slice(len: usize) -> Self {
196        // Safety (although no unsafe is required):
197        // - `ArcInner` is properly allocated and initialized.
198        //   - `()` and `[MaybeUninit<T>]` do not require special initialization
199        // - The `Arc` is just created and so -- unique.
200        let arc: Arc<HeaderSlice<(), [MaybeUninit<T>]>> =
201            UniqueArc::from_header_and_uninit_slice((), len).0;
202        let arc: Arc<[MaybeUninit<T>]> = arc.into();
203        UniqueArc(arc)
204    }
205
206    /// Fallible version of [`UniqueArc::new_uninit_slice`].
207    ///
208    /// Returns `Err(AllocError)` instead of aborting on allocation failure.
209    pub fn try_new_uninit_slice(len: usize) -> Result<Self, AllocError> {
210        let arc: Arc<HeaderSlice<(), [MaybeUninit<T>]>> =
211            UniqueArc::try_from_header_and_uninit_slice((), len)?.0;
212        let arc: Arc<[MaybeUninit<T>]> = arc.into();
213        Ok(UniqueArc(arc))
214    }
215
216    /// # Safety
217    ///
218    /// Must initialize all fields before calling this function.
219    #[inline]
220    pub const unsafe fn assume_init_slice(this: Self) -> UniqueArc<[T]> {
221        UniqueArc(this.shareable().assume_init())
222    }
223}
224
225impl<H, T> UniqueArc<HeaderSlice<H, [MaybeUninit<T>]>> {
226    /// Creates an Arc for a HeaderSlice using the given header struct and allocated space
227    /// for an unitialized slice of length `len`.
228    #[inline]
229    pub fn from_header_and_uninit_slice(header: H, len: usize) -> Self {
230        let inner = Arc::<HeaderSlice<H, [MaybeUninit<T>]>>::allocate_for_header_and_slice(len);
231
232        unsafe {
233            // Safety: inner is a valid pointer, so this can't go out of bounds
234            let dst = addr_of_mut!((*inner.as_ptr()).data.header);
235
236            // Safety: `dst` is valid for writes (just allocated)
237            ptr::write(dst, header);
238        }
239
240        // Safety: ptr is valid & the inner structure is initialized.
241        // We wrote the header above and the slice can stay unitialized as it's [MaybeUninit<T>]
242        Self(Arc {
243            p: inner,
244            phantom: PhantomData,
245        })
246    }
247
248    /// Fallible version of [`UniqueArc::from_header_and_uninit_slice`].
249    ///
250    /// Returns `Err(AllocError)` instead of aborting on allocation failure.
251    #[inline]
252    pub fn try_from_header_and_uninit_slice(header: H, len: usize) -> Result<Self, AllocError> {
253        let inner =
254            Arc::<HeaderSlice<H, [MaybeUninit<T>]>>::try_allocate_for_header_and_slice(len)?;
255
256        unsafe {
257            // Safety: inner is a valid pointer, so this can't go out of bounds
258            let dst = addr_of_mut!((*inner.as_ptr()).data.header);
259
260            // Safety: `dst` is valid for writes (just allocated)
261            ptr::write(dst, header);
262        }
263
264        // Safety: ptr is valid & the inner structure is initialized.
265        // We wrote the header above and the slice can stay unitialized as it's [MaybeUninit<T>]
266        Ok(Self(Arc {
267            p: inner,
268            phantom: PhantomData,
269        }))
270    }
271
272    /// # Safety
273    ///
274    /// Must initialize all fields before calling this function.
275    #[inline]
276    pub const unsafe fn assume_init_slice_with_header(self) -> UniqueArc<HeaderSlice<H, [T]>> {
277        unsafe { core::mem::transmute(self) }
278    }
279}
280
281impl<T: ?Sized> TryFrom<Arc<T>> for UniqueArc<T> {
282    type Error = Arc<T>;
283
284    fn try_from(arc: Arc<T>) -> Result<Self, Self::Error> {
285        Arc::try_unique(arc)
286    }
287}
288
289impl<T: ?Sized> Deref for UniqueArc<T> {
290    type Target = T;
291
292    #[inline]
293    fn deref(&self) -> &T {
294        &self.0
295    }
296}
297
298impl<T: ?Sized> DerefMut for UniqueArc<T> {
299    #[inline]
300    fn deref_mut(&mut self) -> &mut T {
301        // We know this to be uniquely owned
302        unsafe { &mut (*self.0.ptr()).data }
303    }
304}
305
306impl<A> FromIterator<A> for UniqueArc<[A]> {
307    fn from_iter<T: IntoIterator<Item = A>>(iter: T) -> Self {
308        let iter = iter.into_iter();
309        let (lower, upper) = iter.size_hint();
310        let arc: Arc<[A]> = if Some(lower) == upper {
311            let iter = IteratorAsExactSizeIterator::new(iter);
312            Arc::from_header_and_iter((), iter).into()
313        } else {
314            let vec = iter.collect::<Vec<_>>();
315            Arc::from(vec)
316        };
317        // Safety: We just created an `Arc`, so it's unique.
318        unsafe { UniqueArc::from_arc(arc) }
319    }
320}
321
322// Safety:
323// This leverages the correctness of Arc's CoerciblePtr impl. Additionally, we must ensure that
324// this can not be used to violate the safety invariants of UniqueArc, which require that we can not
325// duplicate the Arc, such that replace_ptr returns a valid instance. This holds since it consumes
326// a unique owner of the contained ArcInner.
327#[cfg(feature = "unsize")]
328unsafe impl<T, U: ?Sized> unsize::CoerciblePtr<U> for UniqueArc<T> {
329    type Pointee = T;
330    type Output = UniqueArc<U>;
331
332    fn as_sized_ptr(&mut self) -> *mut T {
333        // Dispatch to the contained field.
334        unsize::CoerciblePtr::<U>::as_sized_ptr(&mut self.0)
335    }
336
337    unsafe fn replace_ptr(self, new: *mut U) -> UniqueArc<U> {
338        // Dispatch to the contained field, work around conflict of destructuring and Drop.
339        let inner = ManuallyDrop::new(self);
340        UniqueArc(ptr::read(&inner.0).replace_ptr(new))
341    }
342}
343
344#[cfg(feature = "serde")]
345impl<'de, T: Deserialize<'de>> Deserialize<'de> for UniqueArc<T> {
346    fn deserialize<D>(deserializer: D) -> Result<UniqueArc<T>, D::Error>
347    where
348        D: ::serde::de::Deserializer<'de>,
349    {
350        T::deserialize(deserializer).map(UniqueArc::new)
351    }
352}
353
354#[cfg(feature = "serde")]
355impl<T: Serialize> Serialize for UniqueArc<T> {
356    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
357    where
358        S: ::serde::ser::Serializer,
359    {
360        (**self).serialize(serializer)
361    }
362}
363
364#[cfg(test)]
365mod tests {
366    use crate::{Arc, HeaderSliceWithLengthUnchecked, HeaderWithLength, UniqueArc};
367    use core::{convert::TryFrom, mem::MaybeUninit};
368
369    #[test]
370    fn unique_into_inner() {
371        let unique = UniqueArc::new(10u64);
372        assert_eq!(UniqueArc::into_inner(unique), 10);
373    }
374
375    #[test]
376    fn try_new() {
377        let unique = UniqueArc::try_new(10u64).unwrap();
378        assert_eq!(UniqueArc::into_inner(unique), 10);
379    }
380
381    #[test]
382    fn try_new_uninit() {
383        let mut arc: UniqueArc<MaybeUninit<_>> = UniqueArc::try_new_uninit().unwrap();
384        arc.write(999);
385
386        let arc = unsafe { UniqueArc::assume_init(arc) };
387        assert_eq!(*arc, 999);
388    }
389
390    #[test]
391    fn try_new_uninit_slice() {
392        let mut arc: UniqueArc<[MaybeUninit<u16>]> = UniqueArc::try_new_uninit_slice(3).unwrap();
393        arc.fill(MaybeUninit::new(2));
394        let arc = unsafe { UniqueArc::assume_init_slice(arc) }.shareable();
395        assert_eq!(&*arc, [2, 2, 2]);
396    }
397
398    #[test]
399    fn try_from_header_and_uninit_slice() {
400        let mut uarc: UniqueArc<HeaderSliceWithLengthUnchecked<u8, MaybeUninit<u16>>> =
401            UniqueArc::try_from_header_and_uninit_slice(HeaderWithLength::new(1, 3), 3).unwrap();
402        uarc.slice.fill(MaybeUninit::new(2));
403        let arc = unsafe { uarc.assume_init_slice_with_header() }.shareable();
404        assert_eq!(arc.header.header, 1);
405        assert_eq!(&arc.slice, [2, 2, 2]);
406    }
407
408    #[test]
409    fn try_from_arc() {
410        let x = Arc::new(10_000);
411        let y = x.clone();
412
413        assert!(UniqueArc::try_from(x).is_err());
414        assert_eq!(
415            UniqueArc::into_inner(UniqueArc::try_from(y).unwrap()),
416            10_000,
417        );
418    }
419
420    #[test]
421    #[allow(deprecated)]
422    fn maybeuninit_smoke() {
423        let mut arc: UniqueArc<MaybeUninit<_>> = UniqueArc::new_uninit();
424        arc.write(999);
425
426        let arc = unsafe { UniqueArc::assume_init(arc) };
427        assert_eq!(*arc, 999);
428    }
429
430    #[test]
431    fn from_header_and_uninit_slice() {
432        let mut uarc: UniqueArc<HeaderSliceWithLengthUnchecked<u8, MaybeUninit<u16>>> =
433            UniqueArc::from_header_and_uninit_slice(HeaderWithLength::new(1, 3), 3);
434        uarc.slice.fill(MaybeUninit::new(2));
435        let arc = unsafe { uarc.assume_init_slice_with_header() }.shareable();
436        assert!(arc.is_unique());
437        // Using clone to that the layout generated in new_uninit_slice is compatible
438        // with ArcInner.
439        let arcs = [
440            arc.clone(),
441            arc.clone(),
442            arc.clone(),
443            arc.clone(),
444            arc.clone(),
445        ];
446        // Similar for ThinArc
447        let thin = Arc::into_thin(arc.clone());
448        assert_eq!(7, Arc::count(&arc));
449        // If the layout is not compatible, then the data might be corrupted.
450        assert_eq!(arc.header.header, 1);
451        assert_eq!(&arc.slice, [2, 2, 2]);
452        assert_eq!(thin.header.header, 1);
453        assert_eq!(&thin.slice, [2, 2, 2]);
454
455        // Drop the arcs and check the count and the content to
456        // make sure it isn't corrupted.
457        drop(arcs);
458        drop(thin);
459        assert!(arc.is_unique());
460        assert_eq!(arc.header.header, 1);
461        assert_eq!(&arc.slice, [2, 2, 2]);
462    }
463}