use alloc::alloc::handle_alloc_error; use alloc::boxed::Box; use core::alloc::Layout; use core::borrow; use core::cmp::Ordering; use core::convert::From; use core::ffi::c_void; use core::fmt; use core::hash::{Hash, Hasher}; use core::marker::PhantomData; use core::mem::{ManuallyDrop, MaybeUninit}; use core::ops::Deref; use core::ptr::{self, NonNull}; use core::sync::atomic; use core::sync::atomic::Ordering::{Acquire, Relaxed, Release}; use core::{isize, usize}; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; #[cfg(feature = "stable_deref_trait")] use stable_deref_trait::{CloneStableDeref, StableDeref}; use crate::{abort, ArcBorrow, HeaderSlice, OffsetArc, UniqueArc}; /// A soft limit on the amount of references that may be made to an `Arc`. /// /// Going above this limit will abort your program (although not /// necessarily) at _exactly_ `MAX_REFCOUNT + 1` references. const MAX_REFCOUNT: usize = (isize::MAX) as usize; /// The object allocated by an Arc #[repr(C)] pub(crate) struct ArcInner { pub(crate) count: atomic::AtomicUsize, pub(crate) data: T, } unsafe impl Send for ArcInner {} unsafe impl Sync for ArcInner {} /// An atomically reference counted shared pointer /// /// See the documentation for [`Arc`] in the standard library. Unlike the /// standard library `Arc`, this `Arc` does not support weak reference counting. /// /// [`Arc`]: https://doc.rust-lang.org/stable/std/sync/struct.Arc.html #[repr(transparent)] pub struct Arc { pub(crate) p: ptr::NonNull>, pub(crate) phantom: PhantomData, } unsafe impl Send for Arc {} unsafe impl Sync for Arc {} impl Arc { /// Construct an `Arc` #[inline] pub fn new(data: T) -> Self { let ptr = Box::into_raw(Box::new(ArcInner { count: atomic::AtomicUsize::new(1), data, })); unsafe { Arc { p: ptr::NonNull::new_unchecked(ptr), phantom: PhantomData, } } } /// Reconstruct the Arc from a raw pointer obtained from into_raw() /// /// Note: This raw pointer will be offset in the allocation and must be preceded /// by the atomic count. /// /// It is recommended to use OffsetArc for this #[inline] pub unsafe fn from_raw(ptr: *const T) -> Self { // FIXME: when `byte_sub` is stabilized, this can accept T: ?Sized. // To find the corresponding pointer to the `ArcInner` we need // to subtract the offset of the `data` field from the pointer. let ptr = (ptr as *const u8).sub(offset_of!(ArcInner, data)); Arc::from_raw_inner(ptr as *mut ArcInner) } /// Temporarily converts |self| into a bonafide OffsetArc and exposes it to the /// provided callback. The refcount is not modified. #[inline(always)] pub fn with_raw_offset_arc(&self, f: F) -> U where F: FnOnce(&OffsetArc) -> U, { // Synthesize transient Arc, which never touches the refcount of the ArcInner. // Store transient in `ManuallyDrop`, to leave the refcount untouched. let transient = unsafe { ManuallyDrop::new(Arc::into_raw_offset(ptr::read(self))) }; // Expose the transient Arc to the callback, which may clone it if it wants. f(&transient) } /// Converts an `Arc` into a `OffsetArc`. This consumes the `Arc`, so the refcount /// is not modified. #[inline] pub fn into_raw_offset(a: Self) -> OffsetArc { unsafe { OffsetArc { ptr: ptr::NonNull::new_unchecked(Arc::into_raw(a) as *mut T), phantom: PhantomData, } } } /// Converts a `OffsetArc` into an `Arc`. This consumes the `OffsetArc`, so the refcount /// is not modified. #[inline] pub fn from_raw_offset(a: OffsetArc) -> Self { let a = ManuallyDrop::new(a); let ptr = a.ptr.as_ptr(); unsafe { Arc::from_raw(ptr) } } /// Returns the inner value, if the [`Arc`] has exactly one strong reference. /// /// Otherwise, an [`Err`] is returned with the same [`Arc`] that was /// passed in. /// /// # Examples /// /// ``` /// use triomphe::Arc; /// /// let x = Arc::new(3); /// assert_eq!(Arc::try_unwrap(x), Ok(3)); /// /// let x = Arc::new(4); /// let _y = Arc::clone(&x); /// assert_eq!(*Arc::try_unwrap(x).unwrap_err(), 4); /// ``` pub fn try_unwrap(this: Self) -> Result { Self::try_unique(this).map(UniqueArc::into_inner) } } impl Arc { /// Convert the Arc to a raw pointer, suitable for use across FFI /// /// Note: This returns a pointer to the data T, which is offset in the allocation. /// /// It is recommended to use OffsetArc for this. #[inline] pub fn into_raw(this: Self) -> *const T { let this = ManuallyDrop::new(this); this.as_ptr() } /// Returns the raw pointer. /// /// Same as into_raw except `self` isn't consumed. #[inline] pub fn as_ptr(&self) -> *const T { // SAFETY: This cannot go through a reference to `data`, because this method // is used to implement `into_raw`. To reconstruct the full `Arc` from this // pointer, it needs to maintain its full provenance, and not be reduced to // just the contained `T`. unsafe { ptr::addr_of_mut!((*self.ptr()).data) } } /// Produce a pointer to the data that can be converted back /// to an Arc. This is basically an `&Arc`, without the extra indirection. /// It has the benefits of an `&T` but also knows about the underlying refcount /// and can be converted into more `Arc`s if necessary. #[inline] pub fn borrow_arc(&self) -> ArcBorrow<'_, T> { ArcBorrow(&**self) } /// Returns the address on the heap of the Arc itself -- not the T within it -- for memory /// reporting. pub fn heap_ptr(&self) -> *const c_void { self.p.as_ptr() as *const ArcInner as *const c_void } #[inline] pub(super) fn into_raw_inner(this: Self) -> *mut ArcInner { let this = ManuallyDrop::new(this); this.ptr() } /// Construct an `Arc` from an allocated `ArcInner`. /// # Safety /// The `ptr` must point to a valid instance, allocated by an `Arc`. The reference could will /// not be modified. pub(super) unsafe fn from_raw_inner(ptr: *mut ArcInner) -> Self { Arc { p: ptr::NonNull::new_unchecked(ptr), phantom: PhantomData, } } #[inline] pub(super) fn inner(&self) -> &ArcInner { // This unsafety is ok because while this arc is alive we're guaranteed // that the inner pointer is valid. Furthermore, we know that the // `ArcInner` structure itself is `Sync` because the inner data is // `Sync` as well, so we're ok loaning out an immutable pointer to these // contents. unsafe { &*self.ptr() } } // Non-inlined part of `drop`. Just invokes the destructor. #[inline(never)] unsafe fn drop_slow(&mut self) { let _ = Box::from_raw(self.ptr()); } /// Test pointer equality between the two Arcs, i.e. they must be the _same_ /// allocation #[inline] pub fn ptr_eq(this: &Self, other: &Self) -> bool { this.ptr() == other.ptr() } pub(crate) fn ptr(&self) -> *mut ArcInner { self.p.as_ptr() } /// Allocates an `ArcInner` with sufficient space for /// a possibly-unsized inner value where the value has the layout provided. /// /// The function `mem_to_arcinner` is called with the data pointer /// and must return back a (potentially fat)-pointer for the `ArcInner`. /// /// ## Safety /// /// `mem_to_arcinner` must return the same pointer, the only things that can change are /// - its type /// - its metadata /// /// `value_layout` must be correct for `T`. #[allow(unused_unsafe)] pub(super) unsafe fn allocate_for_layout( value_layout: Layout, mem_to_arcinner: impl FnOnce(*mut u8) -> *mut ArcInner, ) -> NonNull> { let layout = Layout::new::>() .extend(value_layout) .unwrap() .0 .pad_to_align(); // Safety: we propagate safety requirements to the caller unsafe { Arc::try_allocate_for_layout(value_layout, mem_to_arcinner) .unwrap_or_else(|_| handle_alloc_error(layout)) } } /// Allocates an `ArcInner` with sufficient space for /// a possibly-unsized inner value where the value has the layout provided, /// returning an error if allocation fails. /// /// The function `mem_to_arcinner` is called with the data pointer /// and must return back a (potentially fat)-pointer for the `ArcInner`. /// /// ## Safety /// /// `mem_to_arcinner` must return the same pointer, the only things that can change are /// - its type /// - its metadata /// /// `value_layout` must be correct for `T`. #[allow(unused_unsafe)] unsafe fn try_allocate_for_layout( value_layout: Layout, mem_to_arcinner: impl FnOnce(*mut u8) -> *mut ArcInner, ) -> Result>, ()> { let layout = Layout::new::>() .extend(value_layout) .unwrap() .0 .pad_to_align(); let ptr = NonNull::new(alloc::alloc::alloc(layout)).ok_or(())?; // Initialize the ArcInner let inner = mem_to_arcinner(ptr.as_ptr()); debug_assert_eq!(unsafe { Layout::for_value(&*inner) }, layout); unsafe { ptr::write(&mut (*inner).count, atomic::AtomicUsize::new(1)); } // Safety: `ptr` is checked to be non-null, // `inner` is the same as `ptr` (per the safety requirements of this function) unsafe { Ok(NonNull::new_unchecked(inner)) } } } impl Arc> { pub(super) fn allocate_for_header_and_slice( len: usize, ) -> NonNull>> { let layout = Layout::new::() .extend(Layout::array::(len).unwrap()) .unwrap() .0 .pad_to_align(); unsafe { // Safety: // - the provided closure does not change the pointer (except for meta & type) // - the provided layout is valid for `HeaderSlice` Arc::allocate_for_layout(layout, |mem| { // Synthesize the fat pointer. We do this by claiming we have a direct // pointer to a [T], and then changing the type of the borrow. The key // point here is that the length portion of the fat pointer applies // only to the number of elements in the dynamically-sized portion of // the type, so the value will be the same whether it points to a [T] // or something else with a [T] as its last member. let fake_slice = ptr::slice_from_raw_parts_mut(mem as *mut T, len); fake_slice as *mut ArcInner> }) } } } impl Arc> { /// Create an Arc contains an `MaybeUninit`. pub fn new_uninit() -> Self { Arc::new(MaybeUninit::::uninit()) } /// Calls `MaybeUninit::write` on the value contained. /// /// ## Panics /// /// If the `Arc` is not unique. #[deprecated( since = "0.1.7", note = "this function previously was UB and now panics for non-unique `Arc`s. Use `UniqueArc::write` instead." )] #[track_caller] pub fn write(&mut self, val: T) -> &mut T { UniqueArc::write(must_be_unique(self), val) } /// Obtain a mutable pointer to the stored `MaybeUninit`. pub fn as_mut_ptr(&mut self) -> *mut MaybeUninit { unsafe { &mut (*self.ptr()).data } } /// # Safety /// /// Must initialize all fields before calling this function. #[inline] pub unsafe fn assume_init(self) -> Arc { Arc::from_raw_inner(ManuallyDrop::new(self).ptr().cast()) } } impl Arc<[MaybeUninit]> { /// Create an Arc contains an array `[MaybeUninit]` of `len`. pub fn new_uninit_slice(len: usize) -> Self { UniqueArc::new_uninit_slice(len).shareable() } /// Obtain a mutable slice to the stored `[MaybeUninit]`. #[deprecated( since = "0.1.8", note = "this function previously was UB and now panics for non-unique `Arc`s. Use `UniqueArc` or `get_mut` instead." )] #[track_caller] pub fn as_mut_slice(&mut self) -> &mut [MaybeUninit] { must_be_unique(self) } /// # Safety /// /// Must initialize all fields before calling this function. #[inline] pub unsafe fn assume_init(self) -> Arc<[T]> { Arc::from_raw_inner(ManuallyDrop::new(self).ptr() as _) } } impl Clone for Arc { #[inline] fn clone(&self) -> Self { // Using a relaxed ordering is alright here, as knowledge of the // original reference prevents other threads from erroneously deleting // the object. // // As explained in the [Boost documentation][1], Increasing the // reference counter can always be done with memory_order_relaxed: New // references to an object can only be formed from an existing // reference, and passing an existing reference from one thread to // another must already provide any required synchronization. // // [1]: (www.boost.org/doc/libs/1_55_0/doc/html/atomic/usage_examples.html) let old_size = self.inner().count.fetch_add(1, Relaxed); // However we need to guard against massive refcounts in case someone // is `mem::forget`ing Arcs. If we don't do this the count can overflow // and users will use-after free. We racily saturate to `isize::MAX` on // the assumption that there aren't ~2 billion threads incrementing // the reference count at once. This branch will never be taken in // any realistic program. // // We abort because such a program is incredibly degenerate, and we // don't care to support it. if old_size > MAX_REFCOUNT { abort(); } unsafe { Arc { p: ptr::NonNull::new_unchecked(self.ptr()), phantom: PhantomData, } } } } impl Deref for Arc { type Target = T; #[inline] fn deref(&self) -> &T { &self.inner().data } } impl Arc { /// Makes a mutable reference to the `Arc`, cloning if necessary /// /// This is functionally equivalent to [`Arc::make_mut`][mm] from the standard library. /// /// If this `Arc` is uniquely owned, `make_mut()` will provide a mutable /// reference to the contents. If not, `make_mut()` will create a _new_ `Arc` /// with a copy of the contents, update `this` to point to it, and provide /// a mutable reference to its contents. /// /// This is useful for implementing copy-on-write schemes where you wish to /// avoid copying things if your `Arc` is not shared. /// /// [mm]: https://doc.rust-lang.org/stable/std/sync/struct.Arc.html#method.make_mut #[inline] pub fn make_mut(this: &mut Self) -> &mut T { if !this.is_unique() { // Another pointer exists; clone *this = Arc::new(T::clone(&this)); } unsafe { // This unsafety is ok because we're guaranteed that the pointer // returned is the *only* pointer that will ever be returned to T. Our // reference count is guaranteed to be 1 at this point, and we required // the Arc itself to be `mut`, so we're returning the only possible // reference to the inner data. &mut (*this.ptr()).data } } /// Makes a `UniqueArc` from an `Arc`, cloning if necessary. /// /// If this `Arc` is uniquely owned, `make_unique()` will provide a `UniqueArc` /// containing `this`. If not, `make_unique()` will create a _new_ `Arc` /// with a copy of the contents, update `this` to point to it, and provide /// a `UniqueArc` to it. /// /// This is useful for implementing copy-on-write schemes where you wish to /// avoid copying things if your `Arc` is not shared. #[inline] pub fn make_unique(this: &mut Self) -> &mut UniqueArc { if !this.is_unique() { // Another pointer exists; clone *this = Arc::new(T::clone(&this)); } unsafe { // Safety: this is either unique or just created (which is also unique) UniqueArc::from_arc_ref(this) } } /// If we have the only reference to `T` then unwrap it. Otherwise, clone `T` and return the clone. /// /// Assuming `arc_t` is of type `Arc`, this function is functionally equivalent to `(*arc_t).clone()`, but will avoid cloning the inner value where possible. pub fn unwrap_or_clone(this: Arc) -> T { Self::try_unwrap(this).unwrap_or_else(|this| T::clone(&this)) } } impl Arc { /// Provides mutable access to the contents _if_ the `Arc` is uniquely owned. #[inline] pub fn get_mut(this: &mut Self) -> Option<&mut T> { if this.is_unique() { unsafe { // See make_mut() for documentation of the threadsafety here. Some(&mut (*this.ptr()).data) } } else { None } } /// Provides unique access to the arc _if_ the `Arc` is uniquely owned. pub fn get_unique(this: &mut Self) -> Option<&mut UniqueArc> { Self::try_as_unique(this).ok() } /// Whether or not the `Arc` is uniquely owned (is the refcount 1?). pub fn is_unique(&self) -> bool { // See the extensive discussion in [1] for why this needs to be Acquire. // // [1] https://github.com/servo/servo/issues/21186 Self::count(self) == 1 } /// Gets the number of [`Arc`] pointers to this allocation pub fn count(this: &Self) -> usize { this.inner().count.load(Acquire) } /// Returns a [`UniqueArc`] if the [`Arc`] has exactly one strong reference. /// /// Otherwise, an [`Err`] is returned with the same [`Arc`] that was /// passed in. /// /// # Examples /// /// ``` /// use triomphe::{Arc, UniqueArc}; /// /// let x = Arc::new(3); /// assert_eq!(UniqueArc::into_inner(Arc::try_unique(x).unwrap()), 3); /// /// let x = Arc::new(4); /// let _y = Arc::clone(&x); /// assert_eq!( /// *Arc::try_unique(x).map(UniqueArc::into_inner).unwrap_err(), /// 4, /// ); /// ``` pub fn try_unique(this: Self) -> Result, Self> { if this.is_unique() { // Safety: The current arc is unique and making a `UniqueArc` // from it is sound unsafe { Ok(UniqueArc::from_arc(this)) } } else { Err(this) } } pub(crate) fn try_as_unique(this: &mut Self) -> Result<&mut UniqueArc, &mut Self> { if this.is_unique() { // Safety: The current arc is unique and making a `UniqueArc` // from it is sound unsafe { Ok(UniqueArc::from_arc_ref(this)) } } else { Err(this) } } } impl Drop for Arc { #[inline] fn drop(&mut self) { // Because `fetch_sub` is already atomic, we do not need to synchronize // with other threads unless we are going to delete the object. if self.inner().count.fetch_sub(1, Release) != 1 { return; } // FIXME(bholley): Use the updated comment when [2] is merged. // // This load is needed to prevent reordering of use of the data and // deletion of the data. Because it is marked `Release`, the decreasing // of the reference count synchronizes with this `Acquire` load. This // means that use of the data happens before decreasing the reference // count, which happens before this load, which happens before the // deletion of the data. // // As explained in the [Boost documentation][1], // // > It is important to enforce any possible access to the object in one // > thread (through an existing reference) to *happen before* deleting // > the object in a different thread. This is achieved by a "release" // > operation after dropping a reference (any access to the object // > through this reference must obviously happened before), and an // > "acquire" operation before deleting the object. // // [1]: (www.boost.org/doc/libs/1_55_0/doc/html/atomic/usage_examples.html) // [2]: https://github.com/rust-lang/rust/pull/41714 self.inner().count.load(Acquire); unsafe { self.drop_slow(); } } } impl PartialEq for Arc { fn eq(&self, other: &Arc) -> bool { Self::ptr_eq(self, other) || *(*self) == *(*other) } #[allow(clippy::partialeq_ne_impl)] fn ne(&self, other: &Arc) -> bool { !Self::ptr_eq(self, other) && *(*self) != *(*other) } } impl PartialOrd for Arc { fn partial_cmp(&self, other: &Arc) -> Option { (**self).partial_cmp(&**other) } fn lt(&self, other: &Arc) -> bool { *(*self) < *(*other) } fn le(&self, other: &Arc) -> bool { *(*self) <= *(*other) } fn gt(&self, other: &Arc) -> bool { *(*self) > *(*other) } fn ge(&self, other: &Arc) -> bool { *(*self) >= *(*other) } } impl Ord for Arc { fn cmp(&self, other: &Arc) -> Ordering { (**self).cmp(&**other) } } impl Eq for Arc {} impl fmt::Display for Arc { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(&**self, f) } } impl fmt::Debug for Arc { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Debug::fmt(&**self, f) } } impl fmt::Pointer for Arc { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Pointer::fmt(&self.ptr(), f) } } impl Default for Arc { #[inline] fn default() -> Arc { Arc::new(Default::default()) } } impl Hash for Arc { fn hash(&self, state: &mut H) { (**self).hash(state) } } impl From for Arc { #[inline] fn from(t: T) -> Self { Arc::new(t) } } impl borrow::Borrow for Arc { #[inline] fn borrow(&self) -> &T { &**self } } impl AsRef for Arc { #[inline] fn as_ref(&self) -> &T { &**self } } #[cfg(feature = "stable_deref_trait")] unsafe impl StableDeref for Arc {} #[cfg(feature = "stable_deref_trait")] unsafe impl CloneStableDeref for Arc {} #[cfg(feature = "serde")] impl<'de, T: Deserialize<'de>> Deserialize<'de> for Arc { fn deserialize(deserializer: D) -> Result, D::Error> where D: ::serde::de::Deserializer<'de>, { T::deserialize(deserializer).map(Arc::new) } } #[cfg(feature = "serde")] impl Serialize for Arc { fn serialize(&self, serializer: S) -> Result where S: ::serde::ser::Serializer, { (**self).serialize(serializer) } } // Safety: // This implementation must guarantee that it is sound to call replace_ptr with an unsized variant // of the pointer retuned in `as_sized_ptr`. The basic property of Unsize coercion is that safety // variants and layout is unaffected. The Arc does not rely on any other property of T. This makes // any unsized ArcInner valid for being shared with the sized variant. // This does _not_ mean that any T can be unsized into an U, but rather than if such unsizing is // possible then it can be propagated into the Arc. #[cfg(feature = "unsize")] unsafe impl unsize::CoerciblePtr for Arc { type Pointee = T; type Output = Arc; fn as_sized_ptr(&mut self) -> *mut T { // Returns a pointer to the complete inner. The unsizing itself won't care about the // pointer value and promises not to offset it. self.p.as_ptr() as *mut T } unsafe fn replace_ptr(self, new: *mut U) -> Arc { // Fix the provenance by ensuring that of `self` is used. let inner = ManuallyDrop::new(self); let p = inner.p.as_ptr() as *mut T; // Safety: This points to an ArcInner of the previous self and holds shared ownership since // the old pointer never decremented the reference count. The caller upholds that `new` is // an unsized version of the previous ArcInner. This assumes that unsizing to the fat // pointer tag of an `ArcInner` and `U` is isomorphic under a direct pointer cast since // in reality we unsized *mut T to *mut U at the address of the ArcInner. This is the case // for all currently envisioned unsized types where the tag of T and ArcInner are simply // the same. Arc::from_raw_inner(p.replace_ptr(new) as *mut ArcInner) } } #[track_caller] fn must_be_unique(arc: &mut Arc) -> &mut UniqueArc { match Arc::try_as_unique(arc) { Ok(unique) => unique, Err(this) => panic!("`Arc` must be unique in order for this operation to be safe, there are currently {} copies", Arc::count(this)), } } #[cfg(test)] mod tests { use crate::arc::Arc; use alloc::string::String; use core::mem::MaybeUninit; #[cfg(feature = "unsize")] use unsize::{CoerceUnsize, Coercion}; #[test] fn try_unwrap() { let x = Arc::new(100usize); let y = x.clone(); // The count should be two so `try_unwrap()` should fail assert_eq!(Arc::count(&x), 2); assert!(Arc::try_unwrap(x).is_err()); // Since `x` has now been dropped, the count should be 1 // and `try_unwrap()` should succeed assert_eq!(Arc::count(&y), 1); assert_eq!(Arc::try_unwrap(y), Ok(100)); } #[test] #[cfg(feature = "unsize")] fn coerce_to_slice() { let x = Arc::new([0u8; 4]); let y: Arc<[u8]> = x.clone().unsize(Coercion::to_slice()); assert_eq!((*x).as_ptr(), (*y).as_ptr()); } #[test] #[cfg(feature = "unsize")] fn coerce_to_dyn() { let x: Arc<_> = Arc::new(|| 42u32); let x: Arc<_> = x.unsize(Coercion::<_, dyn Fn() -> u32>::to_fn()); assert_eq!((*x)(), 42); } #[test] #[allow(deprecated)] fn maybeuninit() { let mut arc: Arc> = Arc::new_uninit(); arc.write(999); let arc = unsafe { arc.assume_init() }; assert_eq!(*arc, 999); } #[test] #[allow(deprecated)] #[should_panic = "`Arc` must be unique in order for this operation to be safe"] fn maybeuninit_ub_to_proceed() { let mut uninit = Arc::new_uninit(); let clone = uninit.clone(); let x: &MaybeUninit = &*clone; // This write invalidates `x` reference uninit.write(String::from("nonononono")); // Read invalidated reference to trigger UB let _ = &*x; } #[test] #[allow(deprecated)] #[should_panic = "`Arc` must be unique in order for this operation to be safe"] fn maybeuninit_slice_ub_to_proceed() { let mut uninit = Arc::new_uninit_slice(13); let clone = uninit.clone(); let x: &[MaybeUninit] = &*clone; // This write invalidates `x` reference uninit.as_mut_slice()[0].write(String::from("nonononono")); // Read invalidated reference to trigger UB let _ = &*x; } #[test] fn maybeuninit_array() { let mut arc: Arc<[MaybeUninit<_>]> = Arc::new_uninit_slice(5); assert!(arc.is_unique()); #[allow(deprecated)] for (uninit, index) in arc.as_mut_slice().iter_mut().zip(0..5) { let ptr = uninit.as_mut_ptr(); unsafe { core::ptr::write(ptr, index) }; } let arc = unsafe { arc.assume_init() }; assert!(arc.is_unique()); // Using clone to that the layout generated in new_uninit_slice is compatible // with ArcInner. let arcs = [ arc.clone(), arc.clone(), arc.clone(), arc.clone(), arc.clone(), ]; assert_eq!(6, Arc::count(&arc)); // If the layout is not compatible, then the data might be corrupted. assert_eq!(*arc, [0, 1, 2, 3, 4]); // Drop the arcs and check the count and the content to // make sure it isn't corrupted. drop(arcs); assert!(arc.is_unique()); assert_eq!(*arc, [0, 1, 2, 3, 4]); } #[test] fn roundtrip() { let arc: Arc = Arc::new(0usize); let ptr = Arc::into_raw(arc); unsafe { let _arc = Arc::from_raw(ptr); } } }