pub mod bounded;
pub mod unbounded;
use core::cell::Cell;
use core::fmt;
use core::marker::PhantomData;
use core::mem::ManuallyDrop;
use core::ops::{Deref, DerefMut};
use crate::shared::SlotCell;
#[repr(C)]
pub struct RcCell<T> {
state: Cell<usize>,
value: core::cell::UnsafeCell<ManuallyDrop<T>>,
}
const BORROW_BIT: usize = 1 << (usize::BITS - 1);
const REFCOUNT_MASK: usize = !BORROW_BIT;
impl<T> RcCell<T> {
#[inline]
pub(crate) fn new(value: T) -> Self {
RcCell {
state: Cell::new(1),
value: core::cell::UnsafeCell::new(ManuallyDrop::new(value)),
}
}
#[inline]
pub(crate) fn into_inner(self) -> T {
ManuallyDrop::into_inner(self.value.into_inner())
}
#[inline]
fn refcount(&self) -> usize {
self.state.get() & REFCOUNT_MASK
}
#[inline]
fn inc_ref(&self) {
let state = self.state.get();
debug_assert!(
(state & REFCOUNT_MASK) < REFCOUNT_MASK,
"RcSlot refcount overflow"
);
self.state.set(state + 1);
}
#[inline]
fn dec_ref(&self) -> usize {
let state = self.state.get();
let count = state & REFCOUNT_MASK;
debug_assert!(count > 0, "RcSlot refcount underflow");
self.state.set((state & BORROW_BIT) | (count - 1));
count - 1
}
#[inline]
fn acquire_borrow(&self) {
let state = self.state.get();
assert!(
state & BORROW_BIT == 0,
"RcSlot<{}> already borrowed",
core::any::type_name::<T>()
);
self.state.set(state | BORROW_BIT);
}
#[inline]
fn release_borrow(&self) {
let state = self.state.get();
debug_assert!(state & BORROW_BIT != 0, "release_borrow without borrow");
self.state.set(state & REFCOUNT_MASK);
}
#[inline]
unsafe fn value_ref(&self) -> &T {
unsafe { &*(self.value.get().cast::<T>()) }
}
#[inline]
#[allow(clippy::mut_from_ref)]
unsafe fn value_mut(&self) -> &mut T {
unsafe { &mut *(self.value.get().cast::<T>()) }
}
#[inline]
pub fn value_ptr(&self) -> *mut T {
self.value.get().cast::<T>()
}
#[inline]
unsafe fn drop_value(&self) {
unsafe {
core::ptr::drop_in_place(self.value.get().cast::<T>());
}
}
}
pub struct RcSlot<T> {
ptr: *mut RcCell<T>,
_marker: PhantomData<T>,
}
impl<T> RcSlot<T> {
#[inline]
pub(crate) unsafe fn from_ptr(ptr: *mut RcCell<T>) -> Self {
RcSlot {
ptr,
_marker: PhantomData,
}
}
#[inline]
pub fn as_ptr(&self) -> *mut RcCell<T> {
self.ptr
}
#[inline]
pub fn into_raw(self) -> *mut RcCell<T> {
let ptr = self.ptr;
core::mem::forget(self);
ptr
}
#[inline]
pub unsafe fn from_raw(ptr: *mut RcCell<T>) -> Self {
RcSlot {
ptr,
_marker: PhantomData,
}
}
#[inline]
pub unsafe fn value_ptr(&self) -> *const T {
unsafe { (*self.ptr).value_ptr().cast_const() }
}
#[inline]
pub unsafe fn value_ptr_mut(&self) -> *mut T {
unsafe { (*self.ptr).value_ptr() }
}
#[inline]
pub fn refcount(&self) -> usize {
unsafe { (*self.ptr).refcount() }
}
#[inline]
pub fn borrow(&self) -> Ref<'_, T> {
unsafe { (*self.ptr).acquire_borrow() };
Ref {
cell: self.ptr,
_marker: PhantomData,
}
}
#[inline]
pub fn borrow_mut(&self) -> RefMut<'_, T> {
unsafe { (*self.ptr).acquire_borrow() };
RefMut {
cell: self.ptr,
_marker: PhantomData,
}
}
#[inline]
pub fn pin(&self) -> core::pin::Pin<Ref<'_, T>> {
unsafe { core::pin::Pin::new_unchecked(self.borrow()) }
}
#[inline]
pub fn pin_mut(&self) -> core::pin::Pin<RefMut<'_, T>> {
unsafe { core::pin::Pin::new_unchecked(self.borrow_mut()) }
}
#[inline]
fn inc_ref(&self) {
unsafe { (*self.ptr).inc_ref() };
}
#[inline]
pub(crate) fn dec_ref(&self) -> usize {
unsafe { (*self.ptr).dec_ref() }
}
#[inline]
pub(crate) unsafe fn drop_value(&self) {
unsafe { (*self.ptr).drop_value() };
}
#[inline]
pub(crate) fn slot_cell_ptr(&self) -> *mut SlotCell<RcCell<T>> {
self.ptr.cast()
}
}
impl<T> Clone for RcSlot<T> {
#[inline]
fn clone(&self) -> Self {
self.inc_ref();
RcSlot {
ptr: self.ptr,
_marker: PhantomData,
}
}
}
impl<T: fmt::Debug> fmt::Debug for RcSlot<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("RcSlot")
.field("refcount", &self.refcount())
.finish()
}
}
#[cfg(debug_assertions)]
impl<T> Drop for RcSlot<T> {
fn drop(&mut self) {
#[cfg(feature = "std")]
if std::thread::panicking() {
return;
}
panic!(
"RcSlot<{}> dropped without being freed — call slab.free(handle)",
core::any::type_name::<T>()
);
}
}
pub struct Ref<'a, T> {
cell: *mut RcCell<T>,
_marker: PhantomData<&'a T>,
}
impl<T> Deref for Ref<'_, T> {
type Target = T;
#[inline]
fn deref(&self) -> &T {
unsafe { (*self.cell).value_ref() }
}
}
impl<T> Drop for Ref<'_, T> {
#[inline]
fn drop(&mut self) {
unsafe { (*self.cell).release_borrow() };
}
}
impl<T: fmt::Debug> fmt::Debug for Ref<'_, T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Ref").field("value", &**self).finish()
}
}
pub struct RefMut<'a, T> {
cell: *mut RcCell<T>,
_marker: PhantomData<&'a mut T>,
}
impl<T> Deref for RefMut<'_, T> {
type Target = T;
#[inline]
fn deref(&self) -> &T {
unsafe { (*self.cell).value_ref() }
}
}
impl<T> DerefMut for RefMut<'_, T> {
#[inline]
fn deref_mut(&mut self) -> &mut T {
unsafe { (*self.cell).value_mut() }
}
}
impl<T> Drop for RefMut<'_, T> {
#[inline]
fn drop(&mut self) {
unsafe { (*self.cell).release_borrow() };
}
}
impl<T: fmt::Debug> fmt::Debug for RefMut<'_, T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("RefMut").field("value", &**self).finish()
}
}