use std::{marker, mem};
use crate::{
alloc::tail,
depot::{
arena::pool::{self, recycle},
capacity,
},
};
pub trait Context<'owner, T>: Sized + 'owner
where
T: recycle::Recycle + 'owner,
{
fn released(&self, result: T::Release);
}
#[repr(transparent)]
pub struct Store<T: recycle::Recycle, C> {
block: Storage<T, C>,
}
impl<T: recycle::Recycle, C> Store<T, C> {
pub fn try_init(
capacity: capacity::Count,
context: C,
seed: T::Seed,
) -> Result<Self, crate::alloc::Error> {
Ok(Self {
block: pool::Entry::try_init(capacity, context, |_| T::from_seed(seed))?,
})
}
pub fn vacancy<'owner>(&'owner self) -> Option<pool::Vacant<'owner, T, C, Notify<'owner>>>
where
T: 'owner,
C: Context<'owner, T>,
{
let header = tail::View::new(&self.block).header();
pool::Vacant::new(header)
}
}
impl<T: recycle::Recycle, C> Drop for Store<T, C> {
fn drop(&mut self) {
unsafe { mem::ManuallyDrop::drop(&mut self.block.header_mut().context) };
}
}
pub struct Notify<'a>(marker::PhantomData<fn(&'a ()) -> &'a ()>);
#[derive(Debug)]
pub struct Frozen;
unsafe impl<'owner, T, C> crate::depot::raw::PoolPolicy<T, C> for Notify<'owner>
where
T: recycle::Recycle + 'owner,
C: Context<'owner, T>,
{
fn retire(mut entry: pool::Terminal<'_, T, C>) {
let result = T::recycle(entry.get_mut());
entry.recycle().context.released(result);
}
}
unsafe impl<'owner, T, C> crate::depot::raw::PoolMutable<T, C> for Notify<'owner>
where
T: recycle::Recycle + 'owner,
C: Context<'owner, T>,
{
}
type Storage<T, C> = tail::Block<recycle::Header<T, C>, pool::Entry<T, C>, capacity::Count>;