use super::ref_counted::RefCounted;
use super::{Barrier, Collectible, Ptr};
use std::mem::forget;
use std::ops::Deref;
use std::ptr::{addr_of, NonNull};
use std::sync::atomic::Ordering::Relaxed;
#[derive(Debug)]
pub struct Arc<T> {
instance_ptr: NonNull<RefCounted<T>>,
}
impl<T: 'static> Arc<T> {
#[inline]
pub fn new(t: T) -> Arc<T> {
let boxed = Box::new(RefCounted::new(t));
Arc {
instance_ptr: unsafe { NonNull::new_unchecked(Box::into_raw(boxed)) },
}
}
}
impl<T> Arc<T> {
#[inline]
pub unsafe fn new_unchecked(t: T) -> Arc<T> {
let boxed = Box::new(RefCounted::new(t));
Arc {
instance_ptr: unsafe { NonNull::new_unchecked(Box::into_raw(boxed)) },
}
}
#[inline]
#[must_use]
pub fn ptr<'b>(&self, _barrier: &'b Barrier) -> Ptr<'b, T> {
Ptr::from(self.instance_ptr.as_ptr())
}
#[inline]
pub unsafe fn get_mut(&mut self) -> Option<&mut T> {
self.instance_ptr.as_mut().get_mut()
}
#[inline]
#[must_use]
pub fn as_ptr(&self) -> *const T {
addr_of!(**self.underlying())
}
#[inline]
#[must_use]
pub fn release(mut self, barrier: &Barrier) -> bool {
let released = if self.underlying().drop_ref() {
self.pass_underlying_to_collector(barrier);
true
} else {
false
};
forget(self);
released
}
#[inline]
#[must_use]
pub unsafe fn release_drop_in_place(mut self) -> bool {
let dropped = if self.underlying().drop_ref() {
if !self.instance_ptr.as_mut().drop_and_dealloc() {
let barrier = Barrier::new();
self.pass_underlying_to_collector(&barrier);
}
true
} else {
false
};
forget(self);
dropped
}
#[inline]
pub(super) fn get_underlying_ptr(&self) -> *mut RefCounted<T> {
self.instance_ptr.as_ptr()
}
#[inline]
pub(super) fn from(ptr: NonNull<RefCounted<T>>) -> Arc<T> {
debug_assert_ne!(
unsafe {
ptr.as_ref()
.ref_cnt()
.load(std::sync::atomic::Ordering::Relaxed)
},
0
);
Arc { instance_ptr: ptr }
}
#[inline]
fn underlying(&self) -> &RefCounted<T> {
unsafe { self.instance_ptr.as_ref() }
}
#[inline]
fn pass_underlying_to_collector(&mut self, barrier: &Barrier) {
let dyn_mut_ptr: *mut dyn Collectible =
self.instance_ptr.as_ptr() as *const dyn Collectible as *mut dyn Collectible;
barrier.collect(dyn_mut_ptr);
}
}
impl<T> AsRef<T> for Arc<T> {
#[inline]
fn as_ref(&self) -> &T {
self.underlying()
}
}
impl<T> Clone for Arc<T> {
#[inline]
fn clone(&self) -> Self {
debug_assert_ne!(self.underlying().ref_cnt().load(Relaxed), 0);
self.underlying().add_ref();
Self {
instance_ptr: self.instance_ptr,
}
}
}
impl<T> Deref for Arc<T> {
type Target = T;
#[inline]
fn deref(&self) -> &Self::Target {
self.underlying()
}
}
impl<T> Drop for Arc<T> {
#[inline]
fn drop(&mut self) {
if self.underlying().drop_ref() {
let barrier = Barrier::new();
self.pass_underlying_to_collector(&barrier);
}
}
}
impl<'b, T> TryFrom<Ptr<'b, T>> for Arc<T> {
type Error = Ptr<'b, T>;
#[inline]
fn try_from(ptr: Ptr<'b, T>) -> Result<Self, Self::Error> {
if let Some(arc) = ptr.get_arc() {
Ok(arc)
} else {
Err(ptr)
}
}
}
unsafe impl<T: Send> Send for Arc<T> {}
unsafe impl<T: Sync> Sync for Arc<T> {}