#![allow(unsafe_code)]
use core::mem::ManuallyDrop;
use core::ops::Deref;
use loom::sync::atomic::{AtomicUsize, Ordering};
struct Cell<T> {
strong: AtomicUsize,
value: core::cell::UnsafeCell<ManuallyDrop<T>>,
}
unsafe impl<T: Send + Sync> Send for Cell<T> {}
unsafe impl<T: Send + Sync> Sync for Cell<T> {}
pub(super) struct Arc<T> {
cell: std::sync::Arc<Cell<T>>,
}
pub(super) struct Weak<T> {
cell: std::sync::Arc<Cell<T>>,
}
impl<T> Arc<T> {
pub(super) fn new(value: T) -> Self {
Self {
cell: std::sync::Arc::new(Cell {
strong: AtomicUsize::new(1),
value: core::cell::UnsafeCell::new(ManuallyDrop::new(value)),
}),
}
}
pub(super) fn downgrade(this: &Self) -> Weak<T> {
Weak {
cell: std::sync::Arc::clone(&this.cell),
}
}
pub(super) fn ptr_eq(a: &Self, b: &Self) -> bool {
std::sync::Arc::ptr_eq(&a.cell, &b.cell)
}
pub(super) fn as_ptr(this: &Self) -> *const T {
std::sync::Arc::as_ptr(&this.cell).cast()
}
pub(super) fn into_inner(this: Self) -> Option<T> {
let this = ManuallyDrop::new(this);
let cell = unsafe { core::ptr::read(&this.cell) };
if cell.strong.fetch_sub(1, Ordering::AcqRel) != 1 {
return None;
}
Some(ManuallyDrop::into_inner(unsafe {
core::ptr::read(cell.value.get())
}))
}
}
impl<T> Clone for Arc<T> {
fn clone(&self) -> Self {
self.cell.strong.fetch_add(1, Ordering::Relaxed);
Self {
cell: std::sync::Arc::clone(&self.cell),
}
}
}
impl<T> Deref for Arc<T> {
type Target = T;
fn deref(&self) -> &T {
unsafe { &**self.cell.value.get() }
}
}
impl<T> Drop for Arc<T> {
fn drop(&mut self) {
if self.cell.strong.fetch_sub(1, Ordering::AcqRel) == 1 {
unsafe { ManuallyDrop::drop(&mut *self.cell.value.get()) };
}
}
}
impl<T> Weak<T> {
pub(super) fn upgrade(&self) -> Option<Arc<T>> {
let mut strong = self.cell.strong.load(Ordering::Relaxed);
loop {
if strong == 0 {
return None;
}
match self.cell.strong.compare_exchange(
strong,
strong + 1,
Ordering::Acquire,
Ordering::Relaxed,
) {
Ok(_) => {
return Some(Arc {
cell: std::sync::Arc::clone(&self.cell),
});
}
Err(actual) => strong = actual,
}
}
}
}
impl<T> Clone for Weak<T> {
fn clone(&self) -> Self {
Self {
cell: std::sync::Arc::clone(&self.cell),
}
}
}