use crate::{
alloc::{AllocError, Flags, KBox},
ffi::c_void,
fmt,
init::InPlaceInit,
sync::Refcount,
try_init,
types::ForeignOwnable,
};
use core::{
alloc::Layout,
borrow::{Borrow, BorrowMut},
marker::PhantomData,
mem::{ManuallyDrop, MaybeUninit},
ops::{Deref, DerefMut},
pin::Pin,
ptr::NonNull,
};
use pin_init::{self, pin_data, InPlaceWrite, Init, PinInit};
mod std_vendor;
#[repr(transparent)]
#[derive(core::marker::CoercePointee)]
pub struct Arc<T: ?Sized> {
ptr: NonNull<ArcInner<T>>,
_p: PhantomData<ArcInner<T>>,
}
#[pin_data]
#[repr(C)]
struct ArcInner<T: ?Sized> {
refcount: Refcount,
data: T,
}
impl<T: ?Sized> ArcInner<T> {
unsafe fn container_of(ptr: *const T) -> NonNull<ArcInner<T>> {
let refcount_layout = Layout::new::<Refcount>();
let val_layout = Layout::for_value(unsafe { &*ptr });
let val_offset = unsafe { refcount_layout.extend(val_layout).unwrap_unchecked().1 };
let ptr = ptr as *const ArcInner<T>;
let ptr = unsafe { ptr.byte_sub(val_offset) };
unsafe { NonNull::new_unchecked(ptr.cast_mut()) }
}
}
unsafe impl<T: ?Sized + Sync + Send> Send for Arc<T> {}
unsafe impl<T: ?Sized + Sync + Send> Sync for Arc<T> {}
impl<T> InPlaceInit<T> for Arc<T> {
type PinnedSelf = Self;
#[inline]
fn try_pin_init<E>(init: impl PinInit<T, E>, flags: Flags) -> Result<Self::PinnedSelf, E>
where
E: From<AllocError>,
{
UniqueArc::try_pin_init(init, flags).map(|u| u.into())
}
#[inline]
fn try_init<E>(init: impl Init<T, E>, flags: Flags) -> Result<Self, E>
where
E: From<AllocError>,
{
UniqueArc::try_init(init, flags).map(|u| u.into())
}
}
impl<T> Arc<T> {
pub fn new(contents: T, flags: Flags) -> Result<Self, AllocError> {
let value = ArcInner {
refcount: Refcount::new(1),
data: contents,
};
let inner = KBox::new(value, flags)?;
let inner = KBox::leak(inner).into();
Ok(unsafe { Self::from_inner(inner) })
}
pub const DATA_OFFSET: usize = core::mem::offset_of!(ArcInner<T>, data);
}
impl<T: ?Sized> Arc<T> {
unsafe fn from_inner(inner: NonNull<ArcInner<T>>) -> Self {
Arc {
ptr: inner,
_p: PhantomData,
}
}
pub fn into_raw(self) -> *const T {
let ptr = self.ptr.as_ptr();
core::mem::forget(self);
unsafe { core::ptr::addr_of!((*ptr).data) }
}
pub fn as_ptr(this: &Self) -> *const T {
let ptr = this.ptr.as_ptr();
unsafe { core::ptr::addr_of!((*ptr).data) }
}
pub unsafe fn from_raw(ptr: *const T) -> Self {
let ptr = unsafe { ArcInner::container_of(ptr) };
unsafe { Self::from_inner(ptr) }
}
#[inline]
pub fn as_arc_borrow(&self) -> ArcBorrow<'_, T> {
unsafe { ArcBorrow::new(self.ptr) }
}
pub fn ptr_eq(this: &Self, other: &Self) -> bool {
core::ptr::eq(this.ptr.as_ptr(), other.ptr.as_ptr())
}
pub fn into_unique_or_drop(this: Self) -> Option<Pin<UniqueArc<T>>> {
let this = ManuallyDrop::new(this);
let refcount = unsafe { &this.ptr.as_ref().refcount };
if refcount.dec_and_test() {
refcount.set(1);
Some(Pin::from(UniqueArc {
inner: ManuallyDrop::into_inner(this),
}))
} else {
None
}
}
}
unsafe impl<T: 'static> ForeignOwnable for Arc<T> {
const FOREIGN_ALIGN: usize = <KBox<ArcInner<T>> as ForeignOwnable>::FOREIGN_ALIGN;
type Borrowed<'a> = ArcBorrow<'a, T>;
type BorrowedMut<'a> = Self::Borrowed<'a>;
fn into_foreign(self) -> *mut c_void {
ManuallyDrop::new(self).ptr.as_ptr().cast()
}
unsafe fn from_foreign(ptr: *mut c_void) -> Self {
let inner = unsafe { NonNull::new_unchecked(ptr.cast::<ArcInner<T>>()) };
unsafe { Self::from_inner(inner) }
}
unsafe fn borrow<'a>(ptr: *mut c_void) -> ArcBorrow<'a, T> {
let inner = unsafe { NonNull::new_unchecked(ptr.cast::<ArcInner<T>>()) };
unsafe { ArcBorrow::new(inner) }
}
unsafe fn borrow_mut<'a>(ptr: *mut c_void) -> ArcBorrow<'a, T> {
unsafe { <Self as ForeignOwnable>::borrow(ptr) }
}
}
impl<T: ?Sized> Deref for Arc<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
unsafe { &self.ptr.as_ref().data }
}
}
impl<T: ?Sized> AsRef<T> for Arc<T> {
fn as_ref(&self) -> &T {
self.deref()
}
}
impl<T: ?Sized> Borrow<T> for Arc<T> {
fn borrow(&self) -> &T {
self.deref()
}
}
impl<T: ?Sized> Clone for Arc<T> {
fn clone(&self) -> Self {
unsafe { self.ptr.as_ref() }.refcount.inc();
unsafe { Self::from_inner(self.ptr) }
}
}
impl<T: ?Sized> Drop for Arc<T> {
fn drop(&mut self) {
let is_zero = unsafe { self.ptr.as_ref() }.refcount.dec_and_test();
if is_zero {
unsafe { drop(KBox::from_raw(self.ptr.as_ptr())) };
}
}
}
impl<T: ?Sized> From<UniqueArc<T>> for Arc<T> {
fn from(item: UniqueArc<T>) -> Self {
item.inner
}
}
impl<T: ?Sized> From<Pin<UniqueArc<T>>> for Arc<T> {
fn from(item: Pin<UniqueArc<T>>) -> Self {
unsafe { Pin::into_inner_unchecked(item).inner }
}
}
#[repr(transparent)]
#[derive(core::marker::CoercePointee)]
pub struct ArcBorrow<'a, T: ?Sized + 'a> {
inner: NonNull<ArcInner<T>>,
_p: PhantomData<&'a ()>,
}
impl<T: ?Sized> Clone for ArcBorrow<'_, T> {
fn clone(&self) -> Self {
*self
}
}
impl<T: ?Sized> Copy for ArcBorrow<'_, T> {}
impl<T: ?Sized> ArcBorrow<'_, T> {
unsafe fn new(inner: NonNull<ArcInner<T>>) -> Self {
Self {
inner,
_p: PhantomData,
}
}
pub unsafe fn from_raw(ptr: *const T) -> Self {
let ptr = unsafe { ArcInner::container_of(ptr) };
unsafe { Self::new(ptr) }
}
}
impl<T: ?Sized> From<ArcBorrow<'_, T>> for Arc<T> {
fn from(b: ArcBorrow<'_, T>) -> Self {
ManuallyDrop::new(unsafe { Arc::from_inner(b.inner) })
.deref()
.clone()
}
}
impl<T: ?Sized> Deref for ArcBorrow<'_, T> {
type Target = T;
fn deref(&self) -> &Self::Target {
unsafe { &self.inner.as_ref().data }
}
}
pub struct UniqueArc<T: ?Sized> {
inner: Arc<T>,
}
impl<T> InPlaceInit<T> for UniqueArc<T> {
type PinnedSelf = Pin<Self>;
#[inline]
fn try_pin_init<E>(init: impl PinInit<T, E>, flags: Flags) -> Result<Self::PinnedSelf, E>
where
E: From<AllocError>,
{
UniqueArc::new_uninit(flags)?.write_pin_init(init)
}
#[inline]
fn try_init<E>(init: impl Init<T, E>, flags: Flags) -> Result<Self, E>
where
E: From<AllocError>,
{
UniqueArc::new_uninit(flags)?.write_init(init)
}
}
impl<T> InPlaceWrite<T> for UniqueArc<MaybeUninit<T>> {
type Initialized = UniqueArc<T>;
fn write_init<E>(mut self, init: impl Init<T, E>) -> Result<Self::Initialized, E> {
let slot = self.as_mut_ptr();
unsafe { init.__init(slot)? };
Ok(unsafe { self.assume_init() })
}
fn write_pin_init<E>(mut self, init: impl PinInit<T, E>) -> Result<Pin<Self::Initialized>, E> {
let slot = self.as_mut_ptr();
unsafe { init.__pinned_init(slot)? };
Ok(unsafe { self.assume_init() }.into())
}
}
impl<T> UniqueArc<T> {
pub fn new(value: T, flags: Flags) -> Result<Self, AllocError> {
Ok(Self {
inner: Arc::new(value, flags)?,
})
}
pub fn new_uninit(flags: Flags) -> Result<UniqueArc<MaybeUninit<T>>, AllocError> {
let inner = KBox::try_init::<AllocError>(
try_init!(ArcInner {
refcount: Refcount::new(1),
data <- pin_init::uninit::<T, AllocError>(),
}? AllocError),
flags,
)?;
Ok(UniqueArc {
inner: unsafe { Arc::from_inner(KBox::leak(inner).into()) },
})
}
}
impl<T> UniqueArc<MaybeUninit<T>> {
pub fn write(mut self, value: T) -> UniqueArc<T> {
self.deref_mut().write(value);
unsafe { self.assume_init() }
}
pub unsafe fn assume_init(self) -> UniqueArc<T> {
let inner = ManuallyDrop::new(self).inner.ptr;
UniqueArc {
inner: unsafe { Arc::from_inner(inner.cast()) },
}
}
pub fn init_with<E>(mut self, init: impl Init<T, E>) -> core::result::Result<UniqueArc<T>, E> {
match unsafe { init.__init(self.as_mut_ptr()) } {
Ok(()) => Ok(unsafe { self.assume_init() }),
Err(err) => Err(err),
}
}
pub fn pin_init_with<E>(
mut self,
init: impl PinInit<T, E>,
) -> core::result::Result<Pin<UniqueArc<T>>, E> {
match unsafe { init.__pinned_init(self.as_mut_ptr()) } {
Ok(()) => Ok(unsafe { self.assume_init() }.into()),
Err(err) => Err(err),
}
}
}
impl<T: ?Sized> From<UniqueArc<T>> for Pin<UniqueArc<T>> {
fn from(obj: UniqueArc<T>) -> Self {
unsafe { Pin::new_unchecked(obj) }
}
}
impl<T: ?Sized> Deref for UniqueArc<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
self.inner.deref()
}
}
impl<T: ?Sized> DerefMut for UniqueArc<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe { &mut self.inner.ptr.as_mut().data }
}
}
impl<T: ?Sized> Borrow<T> for UniqueArc<T> {
fn borrow(&self) -> &T {
self.deref()
}
}
impl<T: ?Sized> BorrowMut<T> for UniqueArc<T> {
fn borrow_mut(&mut self) -> &mut T {
self.deref_mut()
}
}
impl<T: fmt::Display + ?Sized> fmt::Display for UniqueArc<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(self.deref(), f)
}
}
impl<T: fmt::Display + ?Sized> fmt::Display for Arc<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(self.deref(), f)
}
}
impl<T: fmt::Debug + ?Sized> fmt::Debug for UniqueArc<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(self.deref(), f)
}
}
impl<T: fmt::Debug + ?Sized> fmt::Debug for Arc<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(self.deref(), f)
}
}