use super::RawSlab;
use super::RawSlabKey;
use super::SlabIndexT;
use crossbeam_channel::{Receiver, Sender};
use std::marker::PhantomData;
use std::sync::Arc;
pub struct DropSlab<T> {
raw_slab: RawSlab<T>,
drop_tx: Sender<SlabIndexT>,
drop_rx: Receiver<SlabIndexT>,
}
impl<T> Default for DropSlab<T> {
fn default() -> Self {
Self::with_capacity(32)
}
}
impl<T> DropSlab<T> {
pub fn new() -> Self {
Default::default()
}
pub fn with_capacity(capacity: SlabIndexT) -> Self {
let (drop_tx, drop_rx) = crossbeam_channel::unbounded();
Self {
raw_slab: RawSlab::with_capacity(capacity),
drop_tx,
drop_rx,
}
}
pub fn process_drops(&mut self) {
for slab_index in self.drop_rx.try_iter() {
let raw_slab_key = RawSlabKey::<T>::new(slab_index);
self.raw_slab.free(raw_slab_key);
}
}
pub fn allocate(
&mut self,
value: T,
) -> DropSlabKey<T> {
let slab_key = self.raw_slab.allocate(value);
DropSlabKey::new(slab_key.index(), self.drop_tx.clone())
}
pub fn get(
&self,
slab_key: &DropSlabKey<T>,
) -> Option<&T> {
self.get_raw(RawSlabKey::new(slab_key.index()))
}
pub fn get_mut(
&mut self,
slab_key: &DropSlabKey<T>,
) -> Option<&mut T> {
self.get_raw_mut(RawSlabKey::new(slab_key.index()))
}
pub fn get_raw(
&self,
raw_slab_key: RawSlabKey<T>,
) -> Option<&T> {
self.raw_slab.get(raw_slab_key)
}
pub fn get_raw_mut(
&mut self,
raw_slab_key: RawSlabKey<T>,
) -> Option<&mut T> {
self.raw_slab.get_mut(raw_slab_key)
}
pub fn iter_values(&self) -> impl Iterator<Item = &T> {
self.raw_slab.iter().map(move |(_, value)| value)
}
pub fn iter_values_mut(&mut self) -> impl Iterator<Item = &mut T> {
self.raw_slab.iter_mut().map(move |(_, value)| value)
}
pub fn allocated_count(&self) -> usize {
self.raw_slab.allocated_count()
}
pub fn storage_size(&self) -> usize {
self.raw_slab.storage_size()
}
}
pub struct RawDropSlabKeyInner {
raw_slab_index: SlabIndexT,
drop_tx: Sender<SlabIndexT>,
}
impl Drop for RawDropSlabKeyInner {
fn drop(&mut self) {
let _ = self.drop_tx.send(self.raw_slab_index);
}
}
pub struct DropSlabKey<T> {
inner: Arc<RawDropSlabKeyInner>,
_phantom: PhantomData<T>,
}
impl<T> Clone for DropSlabKey<T> {
fn clone(&self) -> Self {
Self {
inner: self.inner.clone(),
_phantom: Default::default(),
}
}
}
impl<T> std::fmt::Debug for DropSlabKey<T> {
fn fmt(
&self,
f: &mut std::fmt::Formatter<'_>,
) -> std::fmt::Result {
f.debug_struct("DropSlabKey")
.field("index", &self.inner.raw_slab_index)
.finish()
}
}
impl<T> DropSlabKey<T> {
fn new(
raw_slab_index: SlabIndexT,
drop_tx: Sender<SlabIndexT>,
) -> Self {
let inner = RawDropSlabKeyInner {
raw_slab_index,
drop_tx,
};
Self {
inner: Arc::new(inner),
_phantom: Default::default(),
}
}
pub fn index(&self) -> SlabIndexT {
self.inner.raw_slab_index
}
pub fn generic_drop_slab_key(&self) -> GenericDropSlabKey {
GenericDropSlabKey::new(self.inner.clone())
}
}
pub struct GenericDropSlabKey {
inner: Arc<RawDropSlabKeyInner>,
}
impl Clone for GenericDropSlabKey {
fn clone(&self) -> Self {
Self::new(self.inner.clone())
}
}
impl std::fmt::Debug for GenericDropSlabKey {
fn fmt(
&self,
f: &mut std::fmt::Formatter<'_>,
) -> std::fmt::Result {
f.debug_struct("GenericDropSlabKey")
.field("index", &self.inner.raw_slab_index)
.finish()
}
}
impl GenericDropSlabKey {
fn new(inner: Arc<RawDropSlabKeyInner>) -> Self {
Self { inner }
}
pub fn index(&self) -> SlabIndexT {
self.inner.raw_slab_index
}
pub fn drop_slab_key<T>(&self) -> DropSlabKey<T> {
DropSlabKey {
inner: self.inner.clone(),
_phantom: Default::default(),
}
}
}