use std::ptr::NonNull;
use crate::block::Block;
pub struct ArenaRc<T> {
block: NonNull<Block<T>>,
}
impl<T: std::fmt::Display> std::fmt::Display for ArenaRc<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 ArenaRc<T> {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
std::fmt::Debug::fmt(&**self, f)
}
}
impl<T> std::fmt::Pointer for ArenaRc<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> ArenaRc<T> {
pub(crate) fn new(mut block: NonNull<Block<T>>) -> ArenaRc<T> {
let counter_mut = unsafe { block.as_mut() }.counter.get_mut();
assert!(*counter_mut == 0, "ArenaRc: Counter not zero {}", counter_mut);
*counter_mut = 1;
ArenaRc { block }
}
}
impl<T> Clone for ArenaRc<T> {
#[inline]
fn clone(&self) -> ArenaRc<T> {
let counter_mut = unsafe { &mut *self.block.as_ptr() }.counter.get_mut();
assert!(*counter_mut < isize::max_value() as usize);
*counter_mut += 1;
ArenaRc {
block: self.block
}
}
}
impl<T> std::ops::Deref for ArenaRc<T> {
type Target = T;
fn deref(&self) -> &T {
unsafe { &*self.block.as_ref().value.get() }
}
}
impl<T> Drop for ArenaRc<T> {
fn drop(&mut self) {
let counter_mut = unsafe { self.block.as_mut() }.counter.get_mut();
*counter_mut -= 1;
if *counter_mut == 0 {
Block::drop_block(self.block)
};
}
}
#[cfg(test)]
mod tests {
use crate::Pool;
#[test]
fn arena_rc() {
let pool = Pool::new();
let rc = pool.alloc_rc(10);
assert_eq!(*rc, 10);
let rc2 = rc.clone();
assert_eq!(*rc2, 10);
}
}