use alloc::{alloc::Layout, boxed::Box}; use core::convert::TryFrom; use core::marker::PhantomData; use core::mem::{ManuallyDrop, MaybeUninit}; use core::ops::{Deref, DerefMut}; use core::ptr::{self, NonNull}; use core::sync::atomic::AtomicUsize; use crate::HeaderSlice; use super::{Arc, ArcInner}; /// An `Arc` that is known to be uniquely owned /// /// When `Arc`s are constructed, they are known to be /// uniquely owned. In such a case it is safe to mutate /// the contents of the `Arc`. Normally, one would just handle /// this by mutating the data on the stack before allocating the /// `Arc`, however it's possible the data is large or unsized /// and you need to heap-allocate it earlier in such a way /// that it can be freely converted into a regular `Arc` once you're /// done. /// /// `UniqueArc` exists for this purpose, when constructed it performs /// the same allocations necessary for an `Arc`, however it allows mutable access. /// Once the mutation is finished, you can call `.shareable()` and get a regular `Arc` /// out of it. /// /// ```rust /// # use triomphe::UniqueArc; /// let data = [1, 2, 3, 4, 5]; /// let mut x = UniqueArc::new(data); /// x[4] = 7; // mutate! /// let y = x.shareable(); // y is an Arc /// ``` #[repr(transparent)] pub struct UniqueArc(Arc); impl UniqueArc { #[inline] /// Construct a new UniqueArc pub fn new(data: T) -> Self { UniqueArc(Arc::new(data)) } /// Construct an uninitialized arc #[inline] pub fn new_uninit() -> UniqueArc> { unsafe { let layout = Layout::new::>>(); let ptr = alloc::alloc::alloc(layout); let mut p = NonNull::new(ptr) .unwrap_or_else(|| alloc::alloc::handle_alloc_error(layout)) .cast::>>(); ptr::write(&mut p.as_mut().count, AtomicUsize::new(1)); UniqueArc(Arc { p, phantom: PhantomData, }) } } /// Gets the inner value of the unique arc pub fn into_inner(this: Self) -> T { // Wrap the Arc in a `ManuallyDrop` so that its drop routine never runs let this = ManuallyDrop::new(this.0); debug_assert!( this.is_unique(), "attempted to call `.into_inner()` on a `UniqueArc` with a non-zero ref count", ); // Safety: We have exclusive access to the inner data and the // arc will not perform its drop routine since we've // wrapped it in a `ManuallyDrop` unsafe { Box::from_raw(this.ptr()).data } } } impl UniqueArc { /// Convert to a shareable Arc once we're done mutating it #[inline] pub fn shareable(self) -> Arc { self.0 } /// Creates a new [`UniqueArc`] from the given [`Arc`]. /// /// An unchecked alternative to `Arc::try_unique()` /// /// # Safety /// /// The given `Arc` must have a reference count of exactly one /// pub(crate) unsafe fn from_arc(arc: Arc) -> Self { debug_assert_eq!(Arc::count(&arc), 1); Self(arc) } /// Creates a new `&mut `[`UniqueArc`] from the given `&mut `[`Arc`]. /// /// An unchecked alternative to `Arc::try_as_unique()` /// /// # Safety /// /// The given `Arc` must have a reference count of exactly one pub(crate) unsafe fn from_arc_ref(arc: &mut Arc) -> &mut Self { debug_assert_eq!(Arc::count(&arc), 1); // Safety: caller guarantees that `arc` is unique, // `UniqueArc` is `repr(transparent)` &mut *(arc as *mut Arc as *mut UniqueArc) } } impl UniqueArc> { /// Calls `MaybeUninit::write` on the contained value. pub fn write(&mut self, val: T) -> &mut T { unsafe { // Casting *mut MaybeUninit -> *mut T is always fine let ptr = self.as_mut_ptr() as *mut T; // Safety: We have exclusive access to the inner data ptr.write(val); // Safety: the pointer was just written to &mut *ptr } } /// Obtain a mutable pointer to the stored `MaybeUninit`. pub fn as_mut_ptr(&mut self) -> *mut MaybeUninit { unsafe { &mut (*self.0.ptr()).data } } /// Convert to an initialized Arc. /// /// # Safety /// /// This function is equivalent to `MaybeUninit::assume_init` and has the /// same safety requirements. You are responsible for ensuring that the `T` /// has actually been initialized before calling this method. #[inline] pub unsafe fn assume_init(this: Self) -> UniqueArc { UniqueArc(Arc { p: ManuallyDrop::new(this).0.p.cast(), phantom: PhantomData, }) } } impl UniqueArc<[MaybeUninit]> { /// Create an Arc contains an array `[MaybeUninit]` of `len`. pub fn new_uninit_slice(len: usize) -> Self { let ptr: NonNull]>>> = Arc::allocate_for_header_and_slice(len); // Safety: // - `ArcInner` is properly allocated and initialized. // - `()` and `[MaybeUninit]` do not require special initialization // - The `Arc` is just created and so -- unique. unsafe { let arc: Arc]>> = Arc::from_raw_inner(ptr.as_ptr()); let arc: Arc<[MaybeUninit]> = arc.into(); UniqueArc(arc) } } /// # Safety /// /// Must initialize all fields before calling this function. #[inline] pub unsafe fn assume_init_slice(Self(this): Self) -> UniqueArc<[T]> { UniqueArc(this.assume_init()) } } impl TryFrom> for UniqueArc { type Error = Arc; fn try_from(arc: Arc) -> Result { Arc::try_unique(arc) } } impl Deref for UniqueArc { type Target = T; #[inline] fn deref(&self) -> &T { &*self.0 } } impl DerefMut for UniqueArc { #[inline] fn deref_mut(&mut self) -> &mut T { // We know this to be uniquely owned unsafe { &mut (*self.0.ptr()).data } } } // Safety: // This leverages the correctness of Arc's CoerciblePtr impl. Additionally, we must ensure that // this can not be used to violate the safety invariants of UniqueArc, which require that we can not // duplicate the Arc, such that replace_ptr returns a valid instance. This holds since it consumes // a unique owner of the contained ArcInner. #[cfg(feature = "unsize")] unsafe impl unsize::CoerciblePtr for UniqueArc { type Pointee = T; type Output = UniqueArc; fn as_sized_ptr(&mut self) -> *mut T { // Dispatch to the contained field. unsize::CoerciblePtr::::as_sized_ptr(&mut self.0) } unsafe fn replace_ptr(self, new: *mut U) -> UniqueArc { // Dispatch to the contained field, work around conflict of destructuring and Drop. let inner = ManuallyDrop::new(self); UniqueArc(ptr::read(&inner.0).replace_ptr(new)) } } #[cfg(test)] mod tests { use crate::{Arc, UniqueArc}; use core::{convert::TryFrom, mem::MaybeUninit}; #[test] fn unique_into_inner() { let unique = UniqueArc::new(10u64); assert_eq!(UniqueArc::into_inner(unique), 10); } #[test] fn try_from_arc() { let x = Arc::new(10_000); let y = x.clone(); assert!(UniqueArc::try_from(x).is_err()); assert_eq!( UniqueArc::into_inner(UniqueArc::try_from(y).unwrap()), 10_000, ); } #[test] #[allow(deprecated)] fn maybeuninit_smoke() { let mut arc: UniqueArc> = UniqueArc::new_uninit(); arc.write(999); let arc = unsafe { UniqueArc::assume_init(arc) }; assert_eq!(*arc, 999); } }