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::{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::{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 fn shareable(self) -> Arc<T> {
122        self.0
123    }
124
125    /// Creates a new [`UniqueArc`] from the given [`Arc`].
126    ///
127    /// An unchecked alternative to `Arc::try_unique()`
128    ///
129    /// # Safety
130    ///
131    /// The given `Arc` must have a reference count of exactly one
132    ///
133    pub(crate) unsafe fn from_arc(arc: Arc<T>) -> Self {
134        debug_assert_eq!(Arc::count(&arc), 1);
135        Self(arc)
136    }
137
138    /// Creates a new `&mut `[`UniqueArc`] from the given `&mut `[`Arc`].
139    ///
140    /// An unchecked alternative to `Arc::try_as_unique()`
141    ///
142    /// # Safety
143    ///
144    /// The given `Arc` must have a reference count of exactly one
145    pub(crate) unsafe fn from_arc_ref(arc: &mut Arc<T>) -> &mut Self {
146        debug_assert_eq!(Arc::count(arc), 1);
147
148        // Safety: caller guarantees that `arc` is unique,
149        //         `UniqueArc` is `repr(transparent)`
150        &mut *(arc as *mut Arc<T> as *mut UniqueArc<T>)
151    }
152}
153
154impl<T> UniqueArc<MaybeUninit<T>> {
155    /// Calls `MaybeUninit::write` on the contained value.
156    pub fn write(&mut self, val: T) -> &mut T {
157        unsafe {
158            // Casting *mut MaybeUninit<T> -> *mut T is always fine
159            let ptr = self.as_mut_ptr() as *mut T;
160
161            // Safety: We have exclusive access to the inner data
162            ptr.write(val);
163
164            // Safety: the pointer was just written to
165            &mut *ptr
166        }
167    }
168
169    /// Obtain a mutable pointer to the stored `MaybeUninit<T>`.
170    pub fn as_mut_ptr(&mut self) -> *mut MaybeUninit<T> {
171        unsafe { &mut (*self.0.ptr()).data }
172    }
173
174    /// Convert to an initialized Arc.
175    ///
176    /// # Safety
177    ///
178    /// This function is equivalent to `MaybeUninit::assume_init` and has the
179    /// same safety requirements. You are responsible for ensuring that the `T`
180    /// has actually been initialized before calling this method.
181    #[inline]
182    pub unsafe fn assume_init(this: Self) -> UniqueArc<T> {
183        UniqueArc(Arc {
184            p: ManuallyDrop::new(this).0.p.cast(),
185            phantom: PhantomData,
186        })
187    }
188}
189
190impl<T> UniqueArc<[MaybeUninit<T>]> {
191    /// Create an Arc contains an array `[MaybeUninit<T>]` of `len`.
192    pub fn new_uninit_slice(len: usize) -> Self {
193        // Safety (although no unsafe is required):
194        // - `ArcInner` is properly allocated and initialized.
195        //   - `()` and `[MaybeUninit<T>]` do not require special initialization
196        // - The `Arc` is just created and so -- unique.
197        let arc: Arc<HeaderSlice<(), [MaybeUninit<T>]>> =
198            UniqueArc::from_header_and_uninit_slice((), len).0;
199        let arc: Arc<[MaybeUninit<T>]> = arc.into();
200        UniqueArc(arc)
201    }
202
203    /// Fallible version of [`UniqueArc::new_uninit_slice`].
204    ///
205    /// Returns `Err(AllocError)` instead of aborting on allocation failure.
206    pub fn try_new_uninit_slice(len: usize) -> Result<Self, AllocError> {
207        let arc: Arc<HeaderSlice<(), [MaybeUninit<T>]>> =
208            UniqueArc::try_from_header_and_uninit_slice((), len)?.0;
209        let arc: Arc<[MaybeUninit<T>]> = arc.into();
210        Ok(UniqueArc(arc))
211    }
212
213    /// # Safety
214    ///
215    /// Must initialize all fields before calling this function.
216    #[inline]
217    pub unsafe fn assume_init_slice(Self(this): Self) -> UniqueArc<[T]> {
218        UniqueArc(this.assume_init())
219    }
220}
221
222impl<H, T> UniqueArc<HeaderSlice<H, [MaybeUninit<T>]>> {
223    /// Creates an Arc for a HeaderSlice using the given header struct and allocated space
224    /// for an unitialized slice of length `len`.
225    #[inline]
226    pub fn from_header_and_uninit_slice(header: H, len: usize) -> Self {
227        let inner = Arc::<HeaderSlice<H, [MaybeUninit<T>]>>::allocate_for_header_and_slice(len);
228
229        unsafe {
230            // Safety: inner is a valid pointer, so this can't go out of bounds
231            let dst = addr_of_mut!((*inner.as_ptr()).data.header);
232
233            // Safety: `dst` is valid for writes (just allocated)
234            ptr::write(dst, header);
235        }
236
237        // Safety: ptr is valid & the inner structure is initialized.
238        // We wrote the header above and the slice can stay unitialized as it's [MaybeUninit<T>]
239        Self(Arc {
240            p: inner,
241            phantom: PhantomData,
242        })
243    }
244
245    /// Fallible version of [`UniqueArc::from_header_and_uninit_slice`].
246    ///
247    /// Returns `Err(AllocError)` instead of aborting on allocation failure.
248    #[inline]
249    pub fn try_from_header_and_uninit_slice(header: H, len: usize) -> Result<Self, AllocError> {
250        let inner =
251            Arc::<HeaderSlice<H, [MaybeUninit<T>]>>::try_allocate_for_header_and_slice(len)?;
252
253        unsafe {
254            // Safety: inner is a valid pointer, so this can't go out of bounds
255            let dst = addr_of_mut!((*inner.as_ptr()).data.header);
256
257            // Safety: `dst` is valid for writes (just allocated)
258            ptr::write(dst, header);
259        }
260
261        // Safety: ptr is valid & the inner structure is initialized.
262        // We wrote the header above and the slice can stay unitialized as it's [MaybeUninit<T>]
263        Ok(Self(Arc {
264            p: inner,
265            phantom: PhantomData,
266        }))
267    }
268
269    /// # Safety
270    ///
271    /// Must initialize all fields before calling this function.
272    #[inline]
273    pub unsafe fn assume_init_slice_with_header(self) -> UniqueArc<HeaderSlice<H, [T]>> {
274        unsafe { core::mem::transmute(self) }
275    }
276}
277
278impl<T: ?Sized> TryFrom<Arc<T>> for UniqueArc<T> {
279    type Error = Arc<T>;
280
281    fn try_from(arc: Arc<T>) -> Result<Self, Self::Error> {
282        Arc::try_unique(arc)
283    }
284}
285
286impl<T: ?Sized> Deref for UniqueArc<T> {
287    type Target = T;
288
289    #[inline]
290    fn deref(&self) -> &T {
291        &self.0
292    }
293}
294
295impl<T: ?Sized> DerefMut for UniqueArc<T> {
296    #[inline]
297    fn deref_mut(&mut self) -> &mut T {
298        // We know this to be uniquely owned
299        unsafe { &mut (*self.0.ptr()).data }
300    }
301}
302
303impl<A> FromIterator<A> for UniqueArc<[A]> {
304    fn from_iter<T: IntoIterator<Item = A>>(iter: T) -> Self {
305        let iter = iter.into_iter();
306        let (lower, upper) = iter.size_hint();
307        let arc: Arc<[A]> = if Some(lower) == upper {
308            let iter = IteratorAsExactSizeIterator::new(iter);
309            Arc::from_header_and_iter((), iter).into()
310        } else {
311            let vec = iter.collect::<Vec<_>>();
312            Arc::from(vec)
313        };
314        // Safety: We just created an `Arc`, so it's unique.
315        unsafe { UniqueArc::from_arc(arc) }
316    }
317}
318
319// Safety:
320// This leverages the correctness of Arc's CoerciblePtr impl. Additionally, we must ensure that
321// this can not be used to violate the safety invariants of UniqueArc, which require that we can not
322// duplicate the Arc, such that replace_ptr returns a valid instance. This holds since it consumes
323// a unique owner of the contained ArcInner.
324#[cfg(feature = "unsize")]
325unsafe impl<T, U: ?Sized> unsize::CoerciblePtr<U> for UniqueArc<T> {
326    type Pointee = T;
327    type Output = UniqueArc<U>;
328
329    fn as_sized_ptr(&mut self) -> *mut T {
330        // Dispatch to the contained field.
331        unsize::CoerciblePtr::<U>::as_sized_ptr(&mut self.0)
332    }
333
334    unsafe fn replace_ptr(self, new: *mut U) -> UniqueArc<U> {
335        // Dispatch to the contained field, work around conflict of destructuring and Drop.
336        let inner = ManuallyDrop::new(self);
337        UniqueArc(ptr::read(&inner.0).replace_ptr(new))
338    }
339}
340
341#[cfg(feature = "serde")]
342impl<'de, T: Deserialize<'de>> Deserialize<'de> for UniqueArc<T> {
343    fn deserialize<D>(deserializer: D) -> Result<UniqueArc<T>, D::Error>
344    where
345        D: ::serde::de::Deserializer<'de>,
346    {
347        T::deserialize(deserializer).map(UniqueArc::new)
348    }
349}
350
351#[cfg(feature = "serde")]
352impl<T: Serialize> Serialize for UniqueArc<T> {
353    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
354    where
355        S: ::serde::ser::Serializer,
356    {
357        (**self).serialize(serializer)
358    }
359}
360
361#[cfg(test)]
362mod tests {
363    use crate::{Arc, HeaderSliceWithLengthUnchecked, HeaderWithLength, UniqueArc};
364    use core::{convert::TryFrom, mem::MaybeUninit};
365
366    #[test]
367    fn unique_into_inner() {
368        let unique = UniqueArc::new(10u64);
369        assert_eq!(UniqueArc::into_inner(unique), 10);
370    }
371
372    #[test]
373    fn try_new() {
374        let unique = UniqueArc::try_new(10u64).unwrap();
375        assert_eq!(UniqueArc::into_inner(unique), 10);
376    }
377
378    #[test]
379    fn try_new_uninit() {
380        let mut arc: UniqueArc<MaybeUninit<_>> = UniqueArc::try_new_uninit().unwrap();
381        arc.write(999);
382
383        let arc = unsafe { UniqueArc::assume_init(arc) };
384        assert_eq!(*arc, 999);
385    }
386
387    #[test]
388    fn try_new_uninit_slice() {
389        let mut arc: UniqueArc<[MaybeUninit<u16>]> = UniqueArc::try_new_uninit_slice(3).unwrap();
390        arc.fill(MaybeUninit::new(2));
391        let arc = unsafe { UniqueArc::assume_init_slice(arc) }.shareable();
392        assert_eq!(&*arc, [2, 2, 2]);
393    }
394
395    #[test]
396    fn try_from_header_and_uninit_slice() {
397        let mut uarc: UniqueArc<HeaderSliceWithLengthUnchecked<u8, MaybeUninit<u16>>> =
398            UniqueArc::try_from_header_and_uninit_slice(HeaderWithLength::new(1, 3), 3).unwrap();
399        uarc.slice.fill(MaybeUninit::new(2));
400        let arc = unsafe { uarc.assume_init_slice_with_header() }.shareable();
401        assert_eq!(arc.header.header, 1);
402        assert_eq!(&arc.slice, [2, 2, 2]);
403    }
404
405    #[test]
406    fn try_from_arc() {
407        let x = Arc::new(10_000);
408        let y = x.clone();
409
410        assert!(UniqueArc::try_from(x).is_err());
411        assert_eq!(
412            UniqueArc::into_inner(UniqueArc::try_from(y).unwrap()),
413            10_000,
414        );
415    }
416
417    #[test]
418    #[allow(deprecated)]
419    fn maybeuninit_smoke() {
420        let mut arc: UniqueArc<MaybeUninit<_>> = UniqueArc::new_uninit();
421        arc.write(999);
422
423        let arc = unsafe { UniqueArc::assume_init(arc) };
424        assert_eq!(*arc, 999);
425    }
426
427    #[test]
428    fn from_header_and_uninit_slice() {
429        let mut uarc: UniqueArc<HeaderSliceWithLengthUnchecked<u8, MaybeUninit<u16>>> =
430            UniqueArc::from_header_and_uninit_slice(HeaderWithLength::new(1, 3), 3);
431        uarc.slice.fill(MaybeUninit::new(2));
432        let arc = unsafe { uarc.assume_init_slice_with_header() }.shareable();
433        assert!(arc.is_unique());
434        // Using clone to that the layout generated in new_uninit_slice is compatible
435        // with ArcInner.
436        let arcs = [
437            arc.clone(),
438            arc.clone(),
439            arc.clone(),
440            arc.clone(),
441            arc.clone(),
442        ];
443        // Similar for ThinArc
444        let thin = Arc::into_thin(arc.clone());
445        assert_eq!(7, Arc::count(&arc));
446        // If the layout is not compatible, then the data might be corrupted.
447        assert_eq!(arc.header.header, 1);
448        assert_eq!(&arc.slice, [2, 2, 2]);
449        assert_eq!(thin.header.header, 1);
450        assert_eq!(&thin.slice, [2, 2, 2]);
451
452        // Drop the arcs and check the count and the content to
453        // make sure it isn't corrupted.
454        drop(arcs);
455        drop(thin);
456        assert!(arc.is_unique());
457        assert_eq!(arc.header.header, 1);
458        assert_eq!(&arc.slice, [2, 2, 2]);
459    }
460}