use alloc::boxed::Box;
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;
use core::mem::ManuallyDrop;
use core::ops::Deref;
use core::ptr;
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, OffsetArc, UniqueArc};
const MAX_REFCOUNT: usize = (isize::MAX) as usize;
#[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> {}
#[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> {
#[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,
}
}
}
#[inline]
pub fn into_raw(this: Self) -> *const T {
let ptr = unsafe { &((*this.ptr()).data) as *const _ };
mem::forget(this);
ptr
}
#[inline]
pub unsafe fn from_raw(ptr: *const T) -> Self {
let ptr = (ptr as *const u8).sub(offset_of!(ArcInner<T>, data));
Arc::from_raw_inner(ptr as *mut ArcInner<T>)
}
#[inline]
pub fn borrow_arc(&self) -> ArcBorrow<'_, T> {
ArcBorrow(&**self)
}
#[inline(always)]
pub fn with_raw_offset_arc<F, U>(&self, f: F) -> U
where
F: FnOnce(&OffsetArc<T>) -> U,
{
let transient = unsafe { ManuallyDrop::new(Arc::into_raw_offset(ptr::read(self))) };
let result = f(&transient);
mem::forget(transient);
result
}
pub fn heap_ptr(&self) -> *const c_void {
self.p.as_ptr() as *const ArcInner<T> as *const c_void
}
#[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,
}
}
}
#[inline]
pub fn from_raw_offset(a: OffsetArc<T>) -> Self {
let ptr = a.ptr.as_ptr();
mem::forget(a);
unsafe { Arc::from_raw(ptr) }
}
pub fn try_unwrap(this: Self) -> Result<T, Self> {
Self::try_unique(this).map(UniqueArc::into_inner)
}
}
impl<T: ?Sized> Arc<T> {
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> {
unsafe { &*self.ptr() }
}
#[inline(never)]
unsafe fn drop_slow(&mut self) {
let _ = Box::from_raw(self.ptr());
}
#[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()
}
}
impl<T: ?Sized> Clone for Arc<T> {
#[inline]
fn clone(&self) -> Self {
let old_size = self.inner().count.fetch_add(1, Relaxed);
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 + ?Sized> Arc<T> {
#[inline]
pub fn make_mut(this: &mut Self) -> &mut T {
if !this.is_unique() {
*this = Arc::new((**this).clone());
}
unsafe {
&mut (*this.ptr()).data
}
}
}
impl<T: ?Sized> Arc<T> {
#[inline]
pub fn get_mut(this: &mut Self) -> Option<&mut T> {
if this.is_unique() {
unsafe {
Some(&mut (*this.ptr()).data)
}
} else {
None
}
}
pub fn is_unique(&self) -> bool {
Self::count(self) == 1
}
pub fn count(this: &Self) -> usize {
this.inner().count.load(Acquire)
}
pub fn try_unique(this: Self) -> Result<UniqueArc<T>, Self> {
if this.is_unique() {
unsafe { Ok(UniqueArc::from_arc(this)) }
} else {
Err(this)
}
}
}
impl<T: ?Sized> Drop for Arc<T> {
#[inline]
fn drop(&mut self) {
if self.inner().count.fetch_sub(1, Release) != 1 {
return;
}
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)
}
}
#[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 {
self.p.as_ptr() as *mut T
}
unsafe fn replace_ptr(self, new: *mut U) -> Arc<U> {
let inner = ManuallyDrop::new(self);
let p = inner.p.as_ptr() as *mut T;
Arc::from_raw_inner(p.replace_ptr(new) as *mut ArcInner<U>)
}
}
#[cfg(test)]
mod tests {
use crate::arc::Arc;
#[cfg(feature = "unsize")]
use unsize::{CoerceUnsize, Coercion};
#[test]
fn try_unwrap() {
let x = Arc::new(100usize);
let y = x.clone();
assert_eq!(Arc::count(&x), 2);
assert!(Arc::try_unwrap(x).is_err());
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);
}
}