use core::borrow;
use core::cmp::Ordering;
use core::convert::From;
use core::fmt;
use core::hash::{Hash, Hasher};
use core::marker::PhantomData;
use core::mem;
use core::ops::Deref;
use core::ptr::NonNull;
use core::sync::atomic;
use erasable::{Erasable, ErasedPtr};
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
#[cfg(feature = "stable_deref_trait")]
use stable_deref_trait::{CloneStableDeref, StableDeref};
use crate::{Arc, ArcBorrow, ArcBox, ArcInner};
/// An atomically reference counted shared pointer, which may hold either exactly 0 references (in which case it is analogous to an [`ArcBorrow`])
/// or 1 (in which case it is analogous to an [`Arc`])
#[repr(transparent)]
pub struct ArcRef<'a, T: Erasable> {
pub(crate) p: ErasedPtr,
pub(crate) phantom: PhantomData<&'a T>,
}
unsafe impl<'a, T: Erasable + Sync + Send> Send for ArcRef<'a, T> {}
unsafe impl<'a, T: Erasable + Sync + Send> Sync for ArcRef<'a, T> {}
impl<'a, T: Erasable> ArcRef<'a, T> {
/// Construct an [`ArcRef<'a, T>`]
#[inline]
pub fn new(data: T) -> Self {
ArcRef::from_arc(Arc::new(data))
}
/// Returns the inner value, if the [`ArcRef`] is owned and has exactly one strong reference.
///
/// Otherwise, an [`Err`] is returned with the same [`ArcRef`] that was
/// passed in.
///
/// # Examples
///
/// ```
/// use elysees::ArcRef;
///
/// let x = ArcRef::new(3);
/// assert_eq!(ArcRef::try_unwrap(x), Ok(3));
///
/// let x = ArcRef::new(4);
/// let _y = ArcRef::clone(&x);
/// assert_eq!(*ArcRef::try_unwrap(x).unwrap_err(), 4);
/// ```
#[inline]
pub fn try_unwrap(this: Self) -> Result<T, Self> {
match ArcRef::try_into_arc(this) {
Ok(arc) => Arc::try_unwrap(arc).map_err(ArcRef::from_arc),
Err(borrow) => Err(ArcRef::from_borrow(borrow)),
}
}
/// Makes a mutable reference to the [`ArcRef`], cloning if necessary.
///
/// This is similar to [`ArcRef::make_mut`][mm] from the standard library.
///
/// If this [`ArcRef`] is uniquely owned, `make_mut()` will provide a mutable
/// reference to the contents. If not, `make_mut()` will create a _new_ [`ArcRef`]
/// 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 [`ArcRef`] 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
where
T: Clone,
{
if !ArcRef::is_unique(&this) {
// Another pointer exists *or* this value is borrowed; clone
*this = ArcRef::new((**this).clone());
}
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
}
}
/// Provides mutable access to the contents _if_ the [`ArcRef`] is uniquely owned.
#[inline]
pub fn get_mut(this: &mut Self) -> Option<&mut T> {
if Self::is_unique(this) {
unsafe {
// See make_mut() for documentation of the threadsafety here.
Some(&mut (*this.ptr()).data)
}
} else {
None
}
}
/// Whether or not the [`ArcRef`] is uniquely owned (is the refcount 1, and is `ArcBorrow` itself owned?).
#[inline]
pub fn is_unique(this: &Self) -> bool {
// See the extensive discussion in [1] for why this needs to be Acquire.
//
// [1] https://github.com/servo/servo/issues/21186
ArcRef::is_owned(this) && Self::count(this) == 1
}
/// Gets the number of [`Arc`] pointers to this allocation
#[inline]
pub fn count(this: &Self) -> usize {
Self::load_count(this, atomic::Ordering::Acquire)
}
/// Gets the number of [`Arc`] pointers to this allocation, with a given load ordering
#[inline]
pub fn load_count(this: &Self, order: atomic::Ordering) -> usize {
this.inner().count.load(order)
}
/// Returns an [`ArcBox`] if the [`ArcRef`] has exactly one strong, owned reference.
///
/// Otherwise, an [`Err`] is returned with the same [`ArcRef`] that was
/// passed in.
///
/// # Examples
///
/// ```
/// use elysees::{ArcRef, ArcBox};
///
/// let x = ArcRef::new(3);
/// assert_eq!(ArcBox::into_inner(ArcRef::try_unique(x).unwrap()), 3);
///
/// let x = ArcRef::new(4);
/// let _y = ArcRef::clone(&x);
/// assert_eq!(
/// *ArcRef::try_unique(x).map(ArcBox::into_inner).unwrap_err(),
/// 4,
/// );
/// ```
#[inline]
pub fn try_unique(this: Self) -> Result<ArcBox<T>, Self> {
if ArcRef::is_unique(&this) {
// Safety: The current arc is unique and making a `ArcBox`
// from it is sound
unsafe {
Ok(ArcBox::from_arc(Arc::from_raw_inner(
ArcRef::into_raw_inner(this).0,
)))
}
} else {
Err(this)
}
}
/// Construct an [`ArcRef<'a, T>`] from an [`Arc<T>`]
///
/// # Examples
///
/// ```rust
/// use elysees::{Arc, ArcRef};
///
/// let x = Arc::new(3);
/// let y = ArcRef::from_arc(x.clone());
/// assert_eq!(ArcRef::count(&y), 2);
/// ```
#[inline]
pub fn from_arc(arc: Arc<T>) -> Self {
unsafe { Self::from_raw_inner(arc.into_raw_inner(), true) }
}
/// Construct an `ArcRef<'a, T>` from an `ArcBorrow<'a, T>`
#[inline]
pub fn from_borrow(arc: ArcBorrow<'a, T>) -> Self {
unsafe { Self::from_raw_inner(arc.p, false) }
}
/// Try to convert this `ArcRef<'a, T>` into an `Arc<T>` if owned; otherwise, return it as an `ArcBorrow`
///
/// # Examples
/// ```rust
/// use elysees::ArcRef;
///
/// let x = ArcRef::new(3);
/// assert_eq!(*ArcRef::try_into_arc(x.clone()).unwrap(), 3);
/// ```
#[inline]
pub fn try_into_arc(this: Self) -> Result<Arc<T>, ArcBorrow<'a, T>> {
match this.into_raw_inner() {
(p, true) => Ok(unsafe { Arc::from_raw_inner(p) }),
(p, false) => Err(ArcBorrow {
p,
phantom: PhantomData,
}),
}
}
/// Transform an [`ArcRef`] into an allocated [`ArcInner`] and ownership count.
#[inline]
pub(crate) fn into_raw_inner(self) -> (NonNull<ArcInner<T>>, bool) {
let p = self.nn_ptr();
let o = ArcRef::is_owned(&self);
std::mem::forget(self);
(p, o)
}
/// Construct an [`ArcRef`] from an allocated [`ArcInner`] and ownership count.
/// # Safety
/// The `ptr` must point to a valid instance, allocated by an [`Arc`]. The reference count will
/// not be modified.
#[inline]
pub(crate) unsafe fn from_raw_inner(p: NonNull<ArcInner<T>>, o: bool) -> Self {
ArcRef {
p: Erasable::erase(NonNull::new_unchecked(
(Erasable::erase(p).as_ptr() as usize | if o { 0b10 } else { 0b00 }) as *mut u8,
)),
phantom: PhantomData,
}
}
#[inline]
pub(crate) 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() }
}
/// Test pointer equality between the two [`ArcRef`]s, i.e. they must be the _same_
/// allocation
#[inline]
pub fn ptr_eq(this: &Self, other: &Self) -> bool {
this.nn_ptr() == other.nn_ptr()
}
#[inline]
pub(crate) fn nn_ptr(&self) -> NonNull<ArcInner<T>> {
let buf_ptr = (self.p.as_ptr() as usize & !0b11) as *mut u8;
let erased = unsafe { Erasable::erase(NonNull::new_unchecked(buf_ptr)) };
unsafe { Erasable::unerase(erased) }
}
#[inline]
pub(crate) fn ptr(&self) -> *mut ArcInner<T> {
self.nn_ptr().as_ptr()
}
/// Leak this [`ArcRef`], getting an [`ArcBorrow<'static, T>`]
///
/// You can call the [`get`][`ArcBorrow::get`] method on the returned [`ArcBorrow`] to get an `&'static T`.
/// Note that using this can (obviously) cause memory leaks!
#[inline]
pub fn leak(this: ArcRef<T>) -> ArcBorrow<'static, T> {
let result = ArcBorrow {
p: this.nn_ptr(),
phantom: PhantomData,
};
mem::forget(ArcRef::into_owned(this));
result
}
/// Get whether this [`ArcRef`] is owned
///
/// # Examples
/// ```rust
/// use elysees::ArcRef;
///
/// let x = ArcRef::new(3);
/// assert!(ArcRef::is_owned(&x));
/// let y = x.clone();
/// assert!(ArcRef::is_owned(&y));
/// let z = ArcRef::into_borrow(&x);
/// assert!(!ArcRef::is_owned(&z));
/// ```
#[inline]
pub fn is_owned(this: &Self) -> bool {
this.p.as_ptr() as usize & 0b10 != 0
}
/// Borrow this as an [`ArcBorrow`]. This does *not* bump the refcount.
///
/// # Examples
/// ```rust
/// use elysees::{ArcBorrow, ArcRef};
///
/// let x: ArcRef<u64> = ArcRef::new(3);
/// assert_eq!(ArcRef::count(&x), 1);
/// let y: ArcBorrow<u64> = ArcRef::borrow_arc(&x);
/// assert_eq!(ArcRef::as_ptr(&x), ArcBorrow::into_raw(y));
/// assert_eq!(ArcRef::count(&x), 1);
/// assert_eq!(ArcBorrow::count(y), 1);
/// ```
#[inline]
pub fn borrow_arc(this: &'a Self) -> ArcBorrow<'a, T> {
ArcBorrow {
p: this.nn_ptr(),
phantom: PhantomData,
}
}
/// Get this as an [`Arc`], bumping the refcount if necessary.
///
/// # Examples
/// ```rust
/// use elysees::{Arc, ArcRef};
///
/// let x = ArcRef::new(3);
/// let y = ArcRef::into_borrow(&x);
/// assert_eq!(ArcRef::as_ptr(&x), ArcRef::as_ptr(&y));
/// assert_eq!(ArcRef::count(&x), 1);
/// assert_eq!(ArcRef::count(&y), 1);
/// let z = ArcRef::into_arc(y);
/// assert_eq!(ArcRef::as_ptr(&x), Arc::as_ptr(&z));
/// assert_eq!(ArcRef::count(&x), 2);
/// assert_eq!(Arc::count(&z), 2);
/// let w = ArcRef::into_arc(x);
/// assert_eq!(Arc::count(&w), 2);
/// assert_eq!(Arc::count(&z), 2);
/// ```
#[inline]
pub fn into_arc(this: ArcRef<'a, T>) -> Arc<T> {
match ArcRef::try_into_arc(this) {
Ok(arc) => arc,
Err(borrow) => ArcBorrow::clone_arc(borrow),
}
}
/// Clone this as an [`Arc`].
///
/// # Examples
/// ```rust
/// use elysees::{Arc, ArcRef};
///
/// let x: ArcRef<u64> = ArcRef::new(3);
/// assert_eq!(ArcRef::count(&x), 1);
/// let y: Arc<u64> = ArcRef::clone_arc(&x);
/// assert_eq!(ArcRef::as_ptr(&x), Arc::as_ptr(&y));
/// assert_eq!(ArcRef::count(&x), 2);
/// assert_eq!(Arc::count(&y), 2);
/// ```
#[inline]
pub fn clone_arc(this: &'a Self) -> Arc<T> {
ArcBorrow::clone_arc(ArcRef::borrow_arc(this))
}
/// Get this as an owned [`ArcRef`], with the `'static` lifetime
///
/// # Examples
/// ```rust
/// use elysees::ArcRef;
///
/// let x = ArcRef::new(7);
/// assert_eq!(ArcRef::count(&x), 1);
/// let y = ArcRef::into_borrow(&x);
/// assert_eq!(ArcRef::count(&x), 1);
/// assert_eq!(ArcRef::count(&y), 1);
/// let z = ArcRef::into_owned(y);
/// assert_eq!(ArcRef::as_ptr(&x), ArcRef::as_ptr(&z));
/// assert_eq!(ArcRef::count(&x), 2);
/// assert_eq!(ArcRef::count(&z), 2);
/// ```
#[inline]
pub fn into_owned(this: Self) -> ArcRef<'static, T> {
match Self::try_into_arc(this) {
Ok(arc) => ArcRef::from_arc(arc),
Err(borrow) => ArcRef::from_arc(ArcBorrow::clone_arc(borrow)),
}
}
/// Borrow this as an [`ArcRef`]. This does *not* bump the refcount.
///
/// # Examples
/// ```rust
/// use elysees::ArcRef;
///
/// let x = ArcRef::new(8);
/// assert_eq!(ArcRef::count(&x), 1);
/// let y = ArcRef::into_borrow(&x);
/// assert_eq!(ArcRef::as_ptr(&x), ArcRef::as_ptr(&y));
/// assert_eq!(ArcRef::count(&x), 1);
/// assert_eq!(ArcRef::count(&y), 1);
/// ```
#[inline]
pub fn into_borrow(this: &'a ArcRef<'a, T>) -> ArcRef<'a, T> {
ArcRef::from_borrow(ArcRef::borrow_arc(&this))
}
/// Clone this into an owned [`ArcRef`], with the `'static` lifetime
///
/// # Examples
/// ```rust
/// use elysees::ArcRef;
///
/// let x = ArcRef::new(7);
/// assert_eq!(ArcRef::count(&x), 1);
/// let y = ArcRef::into_borrow(&x);
/// assert_eq!(ArcRef::count(&x), 1);
/// assert_eq!(ArcRef::count(&y), 1);
/// let z = ArcRef::clone_into_owned(&y);
/// assert_eq!(ArcRef::as_ptr(&x), ArcRef::as_ptr(&z));
/// assert_eq!(ArcRef::count(&x), 2);
/// assert_eq!(ArcRef::count(&y), 2);
/// assert_eq!(ArcRef::count(&z), 2);
/// ```
#[inline]
pub fn clone_into_owned(this: &Self) -> ArcRef<'static, T> {
ArcRef::from_arc(ArcRef::clone_arc(this))
}
/// Get the internal pointer of an [`ArcBorrow`]. This does *not* bump the refcount.
///
/// # Examples
/// ```rust
/// use elysees::{Arc, ArcRef};
///
/// let x = ArcRef::new(7);
/// assert_eq!(ArcRef::count(&x), 1);
/// let x_ = x.clone();
/// assert_eq!(ArcRef::count(&x), 2);
/// let p = ArcRef::into_raw(x_);
/// assert_eq!(ArcRef::count(&x), 2);
/// assert_eq!(ArcRef::as_ptr(&x), p);
/// let y = unsafe { Arc::from_raw(p) };
/// assert_eq!(ArcRef::as_ptr(&x), Arc::as_ptr(&y));
/// assert_eq!(ArcRef::count(&x), 2);
/// std::mem::drop(y);
/// assert_eq!(ArcRef::count(&x), 1);
/// ```
#[inline]
pub fn into_raw(this: Self) -> *const T {
let result = ArcBorrow::into_raw(ArcRef::borrow_arc(&this));
mem::forget(this);
result
}
/// Get the internal pointer of an [`ArcBorrow`]. This does *not* bump the refcount.
///
/// # Examples
/// ```rust
/// use elysees::ArcRef;
/// let x = ArcRef::new(7);
/// assert_eq!(ArcRef::count(&x), 1);
/// let p = ArcRef::as_ptr(&x);
/// assert_eq!(ArcRef::count(&x), 1);
/// ```
#[inline]
pub fn as_ptr(this: &Self) -> *const T {
ArcBorrow::into_raw(ArcRef::borrow_arc(this))
}
}
impl<'a, T: Erasable> Drop for ArcRef<'a, T> {
#[inline]
fn drop(&mut self) {
if ArcRef::is_owned(self) {
core::mem::drop(unsafe { Arc::from_raw_inner(self.nn_ptr()) })
}
}
}
impl<'a, T: Erasable> Clone for ArcRef<'a, T> {
#[inline]
fn clone(&self) -> Self {
if ArcRef::is_owned(self) {
ArcRef::from_arc(ArcRef::clone_arc(self))
} else {
ArcRef {
p: self.p,
phantom: PhantomData,
}
}
}
}
impl<'a, T: Erasable> Deref for ArcRef<'a, T> {
type Target = T;
#[inline]
fn deref(&self) -> &T {
&self.inner().data
}
}
impl<'a, 'b, T: Erasable, U: Erasable + PartialEq<T>> PartialEq<ArcRef<'a, T>> for ArcRef<'b, U> {
fn eq(&self, other: &ArcRef<'a, T>) -> bool {
*(*self) == *(*other)
}
#[allow(clippy::partialeq_ne_impl)]
fn ne(&self, other: &ArcRef<'a, T>) -> bool {
*(*self) != *(*other)
}
}
impl<'a, 'b, T: Erasable, U: Erasable + PartialOrd<T>> PartialOrd<ArcRef<'a, T>> for ArcRef<'b, U> {
fn partial_cmp(&self, other: &ArcRef<'a, T>) -> Option<Ordering> {
(**self).partial_cmp(&**other)
}
fn lt(&self, other: &ArcRef<'a, T>) -> bool {
*(*self) < *(*other)
}
fn le(&self, other: &ArcRef<'a, T>) -> bool {
*(*self) <= *(*other)
}
fn gt(&self, other: &ArcRef<'a, T>) -> bool {
*(*self) > *(*other)
}
fn ge(&self, other: &ArcRef<'a, T>) -> bool {
*(*self) >= *(*other)
}
}
impl<'a, T: Erasable + Ord> Ord for ArcRef<'a, T> {
fn cmp(&self, other: &ArcRef<'a, T>) -> Ordering {
(**self).cmp(&**other)
}
}
impl<'a, T: Erasable + Eq> Eq for ArcRef<'a, T> {}
impl<'a, T: Erasable + fmt::Display> fmt::Display for ArcRef<'a, T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Display::fmt(&**self, f)
}
}
impl<'a, T: Erasable + fmt::Debug> fmt::Debug for ArcRef<'a, T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Debug::fmt(&**self, f)
}
}
impl<'a, T: Erasable> fmt::Pointer for ArcRef<'a, T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Pointer::fmt(&self.nn_ptr(), f)
}
}
impl<'a, T: Erasable + Default> Default for ArcRef<'a, T> {
#[inline]
fn default() -> ArcRef<'a, T> {
ArcRef::new(Default::default())
}
}
impl<'a, T: Erasable + Hash> Hash for ArcRef<'a, T> {
fn hash<H: Hasher>(&self, state: &mut H) {
(**self).hash(state)
}
}
impl<'a, T> From<T> for ArcRef<'a, T> {
#[inline]
fn from(t: T) -> Self {
ArcRef::new(t)
}
}
impl<'a, T: Erasable> borrow::Borrow<T> for ArcRef<'a, T> {
#[inline]
fn borrow(&self) -> &T {
&**self
}
}
impl<'a, T: Erasable> AsRef<T> for ArcRef<'a, T> {
#[inline]
fn as_ref(&self) -> &T {
&**self
}
}
#[cfg(feature = "stable_deref_trait")]
unsafe impl<'a, T: Erasable> StableDeref for ArcRef<'a, T> {}
#[cfg(feature = "stable_deref_trait")]
unsafe impl<'a, T: Erasable> CloneStableDeref for ArcRef<'a, T> {}
#[cfg(feature = "serde")]
impl<'a, 'de, T: Deserialize<'de>> Deserialize<'de> for ArcRef<'a, T> {
fn deserialize<D>(deserializer: D) -> Result<ArcRef<'a, T>, D::Error>
where
D: ::serde::de::Deserializer<'de>,
{
T::deserialize(deserializer).map(ArcRef::new)
}
}
#[cfg(feature = "serde")]
impl<'a, T: Serialize> Serialize for ArcRef<'a, T> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: ::serde::ser::Serializer,
{
(**self).serialize(serializer)
}
}