summaryrefslogtreecommitdiffstats
path: root/vendor/triomphe/src/arc.rs
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 03:57:31 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 03:57:31 +0000
commitdc0db358abe19481e475e10c32149b53370f1a1c (patch)
treeab8ce99c4b255ce46f99ef402c27916055b899ee /vendor/triomphe/src/arc.rs
parentReleasing progress-linux version 1.71.1+dfsg1-2~progress7.99u1. (diff)
downloadrustc-dc0db358abe19481e475e10c32149b53370f1a1c.tar.xz
rustc-dc0db358abe19481e475e10c32149b53370f1a1c.zip
Merging upstream version 1.72.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/triomphe/src/arc.rs')
-rw-r--r--vendor/triomphe/src/arc.rs887
1 files changed, 887 insertions, 0 deletions
diff --git a/vendor/triomphe/src/arc.rs b/vendor/triomphe/src/arc.rs
new file mode 100644
index 000000000..6fe022c46
--- /dev/null
+++ b/vendor/triomphe/src/arc.rs
@@ -0,0 +1,887 @@
+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<T>
+#[repr(C)]
+pub(crate) struct ArcInner<T: ?Sized> {
+ pub(crate) count: atomic::AtomicUsize,
+ pub(crate) data: T,
+}
+
+unsafe impl<T: ?Sized + Sync + Send> Send for ArcInner<T> {}
+unsafe impl<T: ?Sized + Sync + Send> Sync for ArcInner<T> {}
+
+/// 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<T: ?Sized> {
+ pub(crate) p: ptr::NonNull<ArcInner<T>>,
+ pub(crate) phantom: PhantomData<T>,
+}
+
+unsafe impl<T: ?Sized + Sync + Send> Send for Arc<T> {}
+unsafe impl<T: ?Sized + Sync + Send> Sync for Arc<T> {}
+
+impl<T> Arc<T> {
+ /// Construct an `Arc<T>`
+ #[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<T> 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<T>, data));
+ Arc::from_raw_inner(ptr as *mut ArcInner<T>)
+ }
+
+ /// 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<F, U>(&self, f: F) -> U
+ where
+ F: FnOnce(&OffsetArc<T>) -> 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<T> {
+ 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<T>) -> 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<T, Self> {
+ Self::try_unique(this).map(UniqueArc::into_inner)
+ }
+}
+
+impl<T: ?Sized> Arc<T> {
+ /// Convert the Arc<T> 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<T>`, 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<T>`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<T> as *const c_void
+ }
+
+ #[inline]
+ pub(super) fn into_raw_inner(this: Self) -> *mut ArcInner<T> {
+ 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<T>) -> Self {
+ Arc {
+ p: ptr::NonNull::new_unchecked(ptr),
+ phantom: PhantomData,
+ }
+ }
+
+ #[inline]
+ pub(super) fn inner(&self) -> &ArcInner<T> {
+ // 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<T> {
+ self.p.as_ptr()
+ }
+
+ /// Allocates an `ArcInner<T>` 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<T>`.
+ ///
+ /// ## 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<T>,
+ ) -> NonNull<ArcInner<T>> {
+ let layout = Layout::new::<ArcInner<()>>()
+ .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<T>` 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<T>`.
+ ///
+ /// ## 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<T>,
+ ) -> Result<NonNull<ArcInner<T>>, ()> {
+ let layout = Layout::new::<ArcInner<()>>()
+ .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<H, T> Arc<HeaderSlice<H, [T]>> {
+ pub(super) fn allocate_for_header_and_slice(
+ len: usize,
+ ) -> NonNull<ArcInner<HeaderSlice<H, [T]>>> {
+ let layout = Layout::new::<H>()
+ .extend(Layout::array::<T>(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<H, [T]>`
+ 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<HeaderSlice<H, [T]>>
+ })
+ }
+ }
+}
+
+impl<T> Arc<MaybeUninit<T>> {
+ /// Create an Arc contains an `MaybeUninit<T>`.
+ pub fn new_uninit() -> Self {
+ Arc::new(MaybeUninit::<T>::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<T>`.
+ pub fn as_mut_ptr(&mut self) -> *mut MaybeUninit<T> {
+ unsafe { &mut (*self.ptr()).data }
+ }
+
+ /// # 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().cast())
+ }
+}
+
+impl<T> Arc<[MaybeUninit<T>]> {
+ /// Create an Arc contains an array `[MaybeUninit<T>]` of `len`.
+ pub fn new_uninit_slice(len: usize) -> Self {
+ UniqueArc::new_uninit_slice(len).shareable()
+ }
+
+ /// Obtain a mutable slice to the stored `[MaybeUninit<T>]`.
+ #[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<T>] {
+ 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<T: ?Sized> Clone for Arc<T> {
+ #[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<T: ?Sized> Deref for Arc<T> {
+ type Target = T;
+
+ #[inline]
+ fn deref(&self) -> &T {
+ &self.inner().data
+ }
+}
+
+impl<T: Clone> Arc<T> {
+ /// 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<T> {
+ 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<T>`, 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>) -> T {
+ Self::try_unwrap(this).unwrap_or_else(|this| T::clone(&this))
+ }
+}
+
+impl<T: ?Sized> Arc<T> {
+ /// 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<T>> {
+ 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<UniqueArc<T>, 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<T>, &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<T: ?Sized> Drop for Arc<T> {
+ #[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<T: ?Sized + PartialEq> PartialEq for Arc<T> {
+ fn eq(&self, other: &Arc<T>) -> bool {
+ Self::ptr_eq(self, other) || *(*self) == *(*other)
+ }
+
+ #[allow(clippy::partialeq_ne_impl)]
+ fn ne(&self, other: &Arc<T>) -> bool {
+ !Self::ptr_eq(self, other) && *(*self) != *(*other)
+ }
+}
+
+impl<T: ?Sized + PartialOrd> PartialOrd for Arc<T> {
+ fn partial_cmp(&self, other: &Arc<T>) -> Option<Ordering> {
+ (**self).partial_cmp(&**other)
+ }
+
+ fn lt(&self, other: &Arc<T>) -> bool {
+ *(*self) < *(*other)
+ }
+
+ fn le(&self, other: &Arc<T>) -> bool {
+ *(*self) <= *(*other)
+ }
+
+ fn gt(&self, other: &Arc<T>) -> bool {
+ *(*self) > *(*other)
+ }
+
+ fn ge(&self, other: &Arc<T>) -> bool {
+ *(*self) >= *(*other)
+ }
+}
+
+impl<T: ?Sized + Ord> Ord for Arc<T> {
+ fn cmp(&self, other: &Arc<T>) -> Ordering {
+ (**self).cmp(&**other)
+ }
+}
+
+impl<T: ?Sized + Eq> Eq for Arc<T> {}
+
+impl<T: ?Sized + fmt::Display> fmt::Display for Arc<T> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ fmt::Display::fmt(&**self, f)
+ }
+}
+
+impl<T: ?Sized + fmt::Debug> fmt::Debug for Arc<T> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ fmt::Debug::fmt(&**self, f)
+ }
+}
+
+impl<T: ?Sized> fmt::Pointer for Arc<T> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ fmt::Pointer::fmt(&self.ptr(), f)
+ }
+}
+
+impl<T: Default> Default for Arc<T> {
+ #[inline]
+ fn default() -> Arc<T> {
+ Arc::new(Default::default())
+ }
+}
+
+impl<T: ?Sized + Hash> Hash for Arc<T> {
+ fn hash<H: Hasher>(&self, state: &mut H) {
+ (**self).hash(state)
+ }
+}
+
+impl<T> From<T> for Arc<T> {
+ #[inline]
+ fn from(t: T) -> Self {
+ Arc::new(t)
+ }
+}
+
+impl<T: ?Sized> borrow::Borrow<T> for Arc<T> {
+ #[inline]
+ fn borrow(&self) -> &T {
+ &**self
+ }
+}
+
+impl<T: ?Sized> AsRef<T> for Arc<T> {
+ #[inline]
+ fn as_ref(&self) -> &T {
+ &**self
+ }
+}
+
+#[cfg(feature = "stable_deref_trait")]
+unsafe impl<T: ?Sized> StableDeref for Arc<T> {}
+#[cfg(feature = "stable_deref_trait")]
+unsafe impl<T: ?Sized> CloneStableDeref for Arc<T> {}
+
+#[cfg(feature = "serde")]
+impl<'de, T: Deserialize<'de>> Deserialize<'de> for Arc<T> {
+ fn deserialize<D>(deserializer: D) -> Result<Arc<T>, D::Error>
+ where
+ D: ::serde::de::Deserializer<'de>,
+ {
+ T::deserialize(deserializer).map(Arc::new)
+ }
+}
+
+#[cfg(feature = "serde")]
+impl<T: Serialize> Serialize for Arc<T> {
+ fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+ 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<T>.
+#[cfg(feature = "unsize")]
+unsafe impl<T, U: ?Sized> unsize::CoerciblePtr<U> for Arc<T> {
+ type Pointee = T;
+ type Output = Arc<U>;
+
+ 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<U> {
+ // 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<U>` 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<T> are simply
+ // the same.
+ Arc::from_raw_inner(p.replace_ptr(new) as *mut ArcInner<U>)
+ }
+}
+
+#[track_caller]
+fn must_be_unique<T: ?Sized>(arc: &mut Arc<T>) -> &mut UniqueArc<T> {
+ 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<MaybeUninit<_>> = 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<String> = &*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<String>] = &*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<usize> = Arc::new(0usize);
+ let ptr = Arc::into_raw(arc);
+ unsafe {
+ let _arc = Arc::from_raw(ptr);
+ }
+ }
+}