use core::ops::DerefMut;
use core::ops::Deref;
use core::{
mem::forget,
sync::atomic::Ordering,
};
use crate::byte_slab::BSlab;
use crate::slab_arc::SlabArc;
pub struct SlabBox<const N: usize, const SZ: usize> {
pub(crate) slab: &'static BSlab<N, SZ>,
pub(crate) idx: usize,
}
impl<const N: usize, const SZ: usize> Drop for SlabBox<N, SZ> {
fn drop(&mut self) {
let arc = unsafe { self.slab.get_idx_unchecked(self.idx).arc };
let zero = arc.compare_exchange(1, 0, Ordering::SeqCst, Ordering::SeqCst);
assert!(zero.is_ok());
if let Ok(q) = self.slab.get_q() {
while let Err(_) = q.enqueue(self.idx) {}
}
}
}
impl<const N: usize, const SZ: usize> Deref for SlabBox<N, SZ> {
type Target = [u8; SZ];
fn deref(&self) -> &Self::Target {
let buf = unsafe { self.slab.get_idx_unchecked(self.idx).buf };
unsafe { &*buf.get() }
}
}
impl<const N: usize, const SZ: usize> DerefMut for SlabBox<N, SZ> {
fn deref_mut(&mut self) -> &mut Self::Target {
let buf = unsafe { self.slab.get_idx_unchecked(self.idx).buf };
unsafe { &mut *buf.get() }
}
}
impl<const N: usize, const SZ: usize> SlabBox<N, SZ> {
pub fn into_arc(self) -> SlabArc<N, SZ> {
let arc = unsafe { self.slab.get_idx_unchecked(self.idx).arc };
let refct = arc.load(Ordering::SeqCst);
assert_eq!(1, refct);
let new_arc = SlabArc {
slab: self.slab,
idx: self.idx,
};
forget(self);
new_arc
}
}
unsafe impl<const N: usize, const SZ: usize> Send for SlabBox<N, SZ> {}