use crate::rt;
use std::borrow::Borrow;
use std::pin::Pin;
use std::{mem, ops, ptr};
#[derive(Debug)]
pub struct Arc<T: ?Sized> {
obj: std::sync::Arc<rt::Arc>,
value: std::sync::Arc<T>,
}
impl<T> Arc<T> {
#[track_caller]
pub fn new(value: T) -> Arc<T> {
let std = std::sync::Arc::new(value);
Arc::from_std(std)
}
pub fn pin(data: T) -> Pin<Arc<T>> {
unsafe { Pin::new_unchecked(Arc::new(data)) }
}
#[track_caller]
pub fn try_unwrap(this: Arc<T>) -> Result<T, Arc<T>> {
if !this.obj.get_mut(location!()) {
return Err(this);
}
assert_eq!(1, std::sync::Arc::strong_count(&this.value));
this.obj.ref_dec(location!());
this.unregister();
let arc_value = unsafe {
let _arc_obj = ptr::read(&this.obj);
let arc_value = ptr::read(&this.value);
mem::forget(this);
arc_value
};
match std::sync::Arc::try_unwrap(arc_value) {
Ok(value) => Ok(value),
Err(_) => unreachable!(),
}
}
}
impl<T: ?Sized> Arc<T> {
#[track_caller]
pub fn from_std(mut std: std::sync::Arc<T>) -> Self {
assert!(
std::sync::Arc::get_mut(&mut std).is_some(),
"Arc provided to `from_std` is not unique"
);
let obj = std::sync::Arc::new(rt::Arc::new(location!()));
let objc = std::sync::Arc::clone(&obj);
rt::execution(|e| {
e.arc_objs
.insert(std::sync::Arc::as_ptr(&std) as *const (), objc);
});
Arc { obj, value: std }
}
#[track_caller]
pub fn strong_count(this: &Self) -> usize {
this.obj.strong_count()
}
#[track_caller]
pub unsafe fn increment_strong_count(ptr: *const T) {
let arc = mem::ManuallyDrop::new(Arc::<T>::from_raw(ptr));
let _arc_clone: mem::ManuallyDrop<_> = arc.clone();
}
#[track_caller]
pub unsafe fn decrement_strong_count(ptr: *const T) {
mem::drop(Arc::from_raw(ptr));
}
#[track_caller]
pub fn get_mut(this: &mut Self) -> Option<&mut T> {
if this.obj.get_mut(location!()) {
assert_eq!(1, std::sync::Arc::strong_count(&this.value));
Some(std::sync::Arc::get_mut(&mut this.value).unwrap())
} else {
None
}
}
pub fn ptr_eq(this: &Self, other: &Self) -> bool {
std::sync::Arc::ptr_eq(&this.value, &other.value)
}
pub fn into_raw(this: Self) -> *const T {
let ptr = Self::as_ptr(&this);
mem::forget(this);
ptr
}
pub fn as_ptr(this: &Self) -> *const T {
std::sync::Arc::as_ptr(&this.value)
}
#[track_caller]
pub unsafe fn from_raw(ptr: *const T) -> Self {
let inner = std::sync::Arc::from_raw(ptr);
let obj = rt::execution(|e| std::sync::Arc::clone(&e.arc_objs[&ptr.cast()]));
Arc { value: inner, obj }
}
fn unregister(&self) {
rt::execution(|e| {
e.arc_objs
.remove(&std::sync::Arc::as_ptr(&self.value).cast())
.expect("Arc object was removed before dropping last Arc");
});
}
}
impl<T: ?Sized> ops::Deref for Arc<T> {
type Target = T;
fn deref(&self) -> &T {
&self.value
}
}
impl<T: ?Sized> Clone for Arc<T> {
#[track_caller]
fn clone(&self) -> Arc<T> {
self.obj.ref_inc(location!());
Arc {
value: self.value.clone(),
obj: self.obj.clone(),
}
}
}
impl<T: ?Sized> Drop for Arc<T> {
#[track_caller]
fn drop(&mut self) {
if self.obj.ref_dec(location!()) {
assert_eq!(
1,
std::sync::Arc::strong_count(&self.value),
"something odd is going on"
);
self.unregister();
}
}
}
impl<T: Default> Default for Arc<T> {
#[track_caller]
fn default() -> Arc<T> {
Arc::new(Default::default())
}
}
impl<T> From<T> for Arc<T> {
#[track_caller]
fn from(t: T) -> Self {
Arc::new(t)
}
}
impl<T: ?Sized> AsRef<T> for Arc<T> {
fn as_ref(&self) -> &T {
self
}
}
impl<T: ?Sized> Borrow<T> for Arc<T> {
fn borrow(&self) -> &T {
self
}
}