use crate::{
ref_counter_api::{DecrementFollowup, RefCounterExt},
ExclusivePin, IntrusivelyCountable, ManagedClone,
};
use alloc::{
borrow::{Cow, ToOwned},
boxed::Box,
};
use core::{
any::{Any, TypeId},
borrow::Borrow,
fmt::{self, Debug, Display, Formatter, Pointer},
hash::{Hash, Hasher},
mem::{self, ManuallyDrop},
ops::Deref,
pin::Pin,
ptr::NonNull,
};
use tap::{Pipe, Tap};
#[repr(transparent)]
pub struct Arc<T: ?Sized + IntrusivelyCountable> {
pointer: NonNull<T>,
}
impl<T: ?Sized + IntrusivelyCountable> AsRef<T> for Arc<T> {
fn as_ref(&self) -> &T {
self
}
}
impl<T: ?Sized + IntrusivelyCountable> Borrow<T> for Arc<T> {
fn borrow(&self) -> &T {
self
}
}
impl<T: ?Sized + IntrusivelyCountable> Clone for Arc<T> {
fn clone(&self) -> Self {
self.ref_counter().increment();
Self {
pointer: self.pointer,
}
}
fn clone_from(&mut self, source: &Self) {
if !Self::ptr_eq(self, source) {
*self = source.clone()
}
}
}
impl<T: ?Sized + IntrusivelyCountable> Debug for Arc<T>
where
T: Debug,
{
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
f.debug_tuple("Arc").field(&&**self).finish()
}
}
impl<T: ?Sized + IntrusivelyCountable> Default for Arc<T>
where
T: Default,
{
fn default() -> Self {
Self::new(T::default())
}
}
impl<T: ?Sized + IntrusivelyCountable> Deref for Arc<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
unsafe { self.pointer.as_ref() }
}
}
impl<T: ?Sized + IntrusivelyCountable> Display for Arc<T>
where
T: Display,
{
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
(**self).fmt(f)
}
}
impl<T: ?Sized + IntrusivelyCountable> Drop for Arc<T> {
fn drop(&mut self) {
unsafe {
match self.ref_counter().decrement() {
DecrementFollowup::LeakIt => (),
DecrementFollowup::DropOrMoveIt => drop(Box::from_raw(self.pointer.as_ptr())),
}
}
}
}
impl<T: ?Sized + IntrusivelyCountable> Eq for Arc<T> where T: Eq {}
impl<T: ?Sized + IntrusivelyCountable> From<Box<T>> for Arc<T> {
fn from(box_: Box<T>) -> Self {
box_.ref_counter().increment();
unsafe { Self::from_raw(NonNull::new_unchecked(Box::leak(box_))) }
}
}
impl<'a, B: ?Sized + IntrusivelyCountable> From<Cow<'a, B>> for Arc<B>
where
B: ToOwned,
Arc<B>: From<B::Owned>,
{
fn from(cow: Cow<'a, B>) -> Self {
match cow {
Cow::Borrowed(b) => b.to_owned().into(),
Cow::Owned(o) => o.into(),
}
}
}
impl<T: Sized + IntrusivelyCountable> From<T> for Arc<T> {
fn from(value: T) -> Self {
Self::new(value)
}
}
impl<T: Sized + IntrusivelyCountable> From<T> for Pin<Arc<T>> {
fn from(value: T) -> Self {
Arc::pin(value)
}
}
impl<T: ?Sized + IntrusivelyCountable> From<Pin<Arc<T>>> for Arc<T>
where
T: Unpin,
{
fn from(pinned: Pin<Arc<T>>) -> Self {
unsafe { Pin::into_inner_unchecked(pinned) }
}
}
impl<T: ?Sized + IntrusivelyCountable> From<Arc<T>> for Pin<Arc<T>>
where
T: Unpin,
{
fn from(unpinned: Arc<T>) -> Self {
unsafe { Pin::new_unchecked(unpinned) }
}
}
impl<T: ?Sized + IntrusivelyCountable> Hash for Arc<T>
where
T: Hash,
{
fn hash<H: Hasher>(&self, state: &mut H) {
(**self).hash(state)
}
}
impl<T: ?Sized + IntrusivelyCountable> Ord for Arc<T>
where
T: Ord,
{
fn cmp(&self, other: &Self) -> core::cmp::Ordering {
(**self).cmp(other)
}
}
impl<T: ?Sized + IntrusivelyCountable, O: ?Sized + IntrusivelyCountable> PartialEq<Arc<O>>
for Arc<T>
where
T: PartialEq<O>,
{
fn eq(&self, other: &Arc<O>) -> bool {
(**self) == (**other)
}
}
impl<T: ?Sized + IntrusivelyCountable, O: ?Sized + IntrusivelyCountable> PartialOrd<Arc<O>>
for Arc<T>
where
T: PartialOrd<O>,
{
fn partial_cmp(&self, other: &Arc<O>) -> Option<core::cmp::Ordering> {
(**self).partial_cmp(other)
}
}
impl<T: ?Sized + IntrusivelyCountable> Pointer for Arc<T> {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
Pointer::fmt(&self.pointer, f)
}
}
unsafe impl<T: ?Sized + IntrusivelyCountable> Send for Arc<T> where T: Sync + Send {}
unsafe impl<T: ?Sized + IntrusivelyCountable> Sync for Arc<T> where T: Sync + Send {}
impl<T: ?Sized + IntrusivelyCountable> Unpin for Arc<T> {}
impl<T: ?Sized + IntrusivelyCountable> Arc<T> {
#[must_use]
pub fn new(value: T) -> Self
where
T: Sized,
{
value.ref_counter().increment();
let instance = Box::leak(Box::new(value));
unsafe { Self::from_raw(NonNull::new_unchecked(instance)) }
}
#[must_use]
pub fn pin(value: T) -> Pin<Self>
where
T: Sized,
{
value.ref_counter().increment();
let instance = Box::leak(Box::new(value));
unsafe { Pin::new_unchecked(Self::from_raw(NonNull::new_unchecked(instance))) }
}
pub fn try_unpin(this: Pin<Self>) -> Result<T, Pin<Self>>
where
T: Sized + Unpin,
{
Pin::into_inner(this)
.pipe(Self::try_unwrap)
.map_err(Pin::new)
}
pub fn try_unwrap(this: Self) -> Result<T, Self>
where
T: Sized,
{
match unsafe { this.ref_counter().acquire() } {
None => Err(this),
Some(exclusivity) => unsafe {
drop(exclusivity); Ok(ManuallyDrop::take(
&mut mem::transmute::<Self, Arc<ManuallyDrop<T>>>(this)
.pointer
.as_mut(),
)
.tap_mut(|unwrapped| unwrapped.ref_counter().decrement_relaxed().pipe(drop)))
},
}
}
#[must_use = "Implicitly dropping this handle is likely a mistake."]
pub unsafe fn from_raw(raw_value: NonNull<T>) -> Self {
debug_assert_ne!(
raw_value.as_ptr().cast::<()>() as usize,
0,
"Called `tiptoe::Arc::from_raw` with null pointer."
);
Self { pointer: raw_value }
}
#[must_use = "Implicitly dropping this handle is likely a mistake."]
pub unsafe fn pinned_from_raw(raw_value: NonNull<T>) -> Pin<Self> {
debug_assert_ne!(
raw_value.as_ptr().cast::<()>() as usize,
0,
"Called `tiptoe::Arc::from_raw` with null pointer."
);
Self { pointer: raw_value }.pipe(|this| Pin::new_unchecked(this))
}
#[must_use]
pub unsafe fn borrow_from_inner_ref<'a>(inner: &'a &'a T) -> &'a Self {
&*(inner as *const &T).cast::<Self>()
}
#[must_use]
pub unsafe fn borrow_pin_from_inner_ref<'a>(inner: &'a &'a T) -> &'a Pin<Self> {
&*(inner as *const &T).cast::<Pin<Self>>()
}
#[must_use = "Ignoring this pointer will usually lead to the underlying payload instance leaking."]
pub fn leak(this: Self) -> NonNull<T> {
let pointer = this.pointer;
mem::forget(this);
pointer
}
#[must_use = "Ignoring this pointer will usually lead to the underlying payload instance leaking."]
pub fn leak_pinned(this: Pin<Self>) -> NonNull<T> {
let this = unsafe { Pin::into_inner_unchecked(this) };
let pointer = this.pointer;
mem::forget(this);
pointer
}
#[must_use]
pub fn ptr_eq(this: &Self, other: &Self) -> bool {
this.pointer == other.pointer
}
pub fn make_mut(this: &mut Pin<Self>) -> ExclusivePin<T>
where
T: Sized + ManagedClone,
{
let exclusivity = unsafe { this.ref_counter().acquire() }.unwrap_or_else(|| {
*this = unsafe {
(&**this).managed_clone().pipe(Self::pin)
};
unsafe { this.ref_counter().acquire() }.expect("unreachable")
});
ExclusivePin::new(exclusivity, unsafe {
Pin::new_unchecked(
(*(this as *mut Pin<Self>).cast::<Arc<T>>())
.pointer
.as_mut(),
)
})
}
#[must_use]
pub fn get_mut(this: &mut Pin<Self>) -> Option<ExclusivePin<T>> {
unsafe { this.ref_counter().acquire() }.map(|exclusivity| {
ExclusivePin::new(exclusivity, unsafe {
Pin::new_unchecked(
(*(this as *mut Pin<Self>).cast::<Arc<T>>())
.pointer
.as_mut(),
)
})
})
}
pub fn downcast<U>(this: Self) -> Result<Arc<U>, Self>
where
T: Any,
U: Any + IntrusivelyCountable,
{
if Any::type_id(&*this) == TypeId::of::<U>() {
Ok(unsafe { Arc::from_raw(Arc::leak(this).cast()) })
} else {
Err(this)
}
}
pub fn downcast_pinned<U>(this: Pin<Self>) -> Result<Pin<Arc<U>>, Pin<Self>>
where
T: Any,
U: Any + IntrusivelyCountable,
{
if Any::type_id(&*this) == TypeId::of::<U>() {
Ok(unsafe { Arc::pinned_from_raw(Arc::leak_pinned(this).cast()) })
} else {
Err(this)
}
}
}