use std::sync::atomic::Ordering::*;
use std::ptr::NonNull;
use crate::block::Block;
pub struct ArenaArc<T> {
block: NonNull<Block<T>>,
}
unsafe impl<T: Send> Send for ArenaArc<T> {}
unsafe impl<T: Send + Sync> Sync for ArenaArc<T> {}
impl<T: std::fmt::Display> std::fmt::Display for ArenaArc<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(&**self, f)
}
}
impl<T: std::fmt::Debug> std::fmt::Debug for ArenaArc<T> {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
std::fmt::Debug::fmt(&**self, f)
}
}
impl<T> std::fmt::Pointer for ArenaArc<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let ptr: *const T = &**self;
std::fmt::Pointer::fmt(&ptr, f)
}
}
impl<T> ArenaArc<T> {
pub(crate) fn new(block: NonNull<Block<T>>) -> ArenaArc<T> {
let counter_ref = &unsafe { block.as_ref() }.counter;
let counter = counter_ref.load(Relaxed);
assert!(counter == 0, "PoolArc: Counter not zero {}", counter);
counter_ref.store(1, Relaxed);
ArenaArc { block }
}
}
impl<T> Clone for ArenaArc<T> {
#[inline]
fn clone(&self) -> ArenaArc<T> {
let counter_ref = &unsafe { self.block.as_ref() }.counter;
let old = counter_ref.fetch_add(1, Relaxed);
assert!(old < isize::max_value() as usize);
ArenaArc {
block: self.block
}
}
}
impl<T> std::ops::Deref for ArenaArc<T> {
type Target = T;
fn deref(&self) -> &T {
unsafe { &*self.block.as_ref().value.get() }
}
}
impl<T> Drop for ArenaArc<T> {
fn drop(&mut self) {
let block = unsafe { self.block.as_ref() };
let count = block.counter.fetch_sub(1, AcqRel);
if count == 1 {
Block::drop_block(self.block)
};
}
}