use std::{cell, marker, mem, ops, pin, ptr};
use crate::{
depot::arena::pool::{
self,
recycle::release,
shared::{Header, Initialized, Resident},
},
mem::rc,
};
pub mod recycle;
pub mod shared;
pub struct Vacant<
'a,
T,
O: crate::depot::raw::PoolOwner<T>,
P: crate::depot::raw::PoolPolicy<T, O> = (),
> {
entry: ptr::NonNull<pool::Entry<T, O>>,
owner: &'a O,
policy: marker::PhantomData<P>,
}
#[repr(transparent)]
pub struct Unique<
'a,
T,
O: crate::depot::raw::PoolOwner<T>,
P: crate::depot::raw::PoolPolicy<T, O> = (),
M = (),
> {
entry: ptr::NonNull<pool::Entry<T, O>>,
owner: marker::PhantomData<fn(&'a O, P, M) -> &'a O>,
}
#[derive(Debug)]
#[repr(transparent)]
pub struct Shared<
'a,
T: crate::mem::raw::Edge,
O: crate::depot::raw::PoolSharing<T>,
P: crate::depot::raw::PoolPolicy<T, O>,
> {
entry: crate::mem::raw::Owner<pool::Counted<T, O, P>>,
owner: marker::PhantomData<fn(&'a O, P) -> &'a O>,
}
impl<'a, T, O: crate::depot::raw::PoolOwner<T>, P: crate::depot::raw::PoolPolicy<T, O>>
Vacant<'a, T, O, P>
{
pub(crate) fn new(owner: &'a O) -> Option<Self> {
let free = unsafe { owner.free() };
let entry = ptr::NonNull::new(free.get())?;
free.set(unsafe { entry.as_ref().state.get().cast() });
Some(Self {
entry,
owner,
policy: marker::PhantomData,
})
}
pub fn reserve(self) -> Unique<'a, T, O, P> {
let this = mem::ManuallyDrop::new(self);
unsafe {
this.entry
.as_ref()
.state
.set(ptr::from_ref(this.owner).cast_mut())
};
Unique {
entry: this.entry,
owner: marker::PhantomData,
}
}
}
impl<T, O: crate::depot::raw::PoolOwner<T>, P: crate::depot::raw::PoolPolicy<T, O>> Drop
for Vacant<'_, T, O, P>
{
fn drop(&mut self) {
unsafe { pool::Entry::recycle(self.entry, self.owner.free()) };
}
}
impl<'a, T, O: crate::depot::raw::PoolOwner<T>, P: crate::depot::raw::PoolPolicy<T, O>, M>
Unique<'a, T, O, P, M>
{
pub fn get(&self) -> pin::Pin<&T> {
unsafe { pin::Pin::new_unchecked(&self.entry.as_ref().value) }
}
}
impl<T, O: crate::depot::raw::PoolOwner<T>, P: crate::depot::raw::PoolMutable<T, O>>
Unique<'_, T, O, P>
{
pub fn get_mut(&mut self) -> pin::Pin<&mut T> {
unsafe { pin::Pin::new_unchecked(&mut self.entry.as_mut().value) }
}
}
impl<
'a,
T: crate::mem::raw::Edge,
O: crate::depot::raw::PoolSharing<T>,
P: crate::depot::raw::PoolPolicy<T, O>,
> Unique<'a, T, O, P>
{
pub fn freeze(self) -> Shared<'a, T, O, P> {
unsafe { self.get().get_ref().activate() };
let this = mem::ManuallyDrop::new(self);
Shared {
entry: unsafe { crate::mem::raw::Owner::from_raw(this.entry.cast()) },
owner: marker::PhantomData,
}
}
pub fn freeze_pair(self) -> (Shared<'a, T, O, P>, Shared<'a, T, O, P>) {
unsafe { self.get().get_ref().start_pair() };
let this = mem::ManuallyDrop::new(self);
(
Shared {
entry: unsafe { crate::mem::raw::Owner::from_raw(this.entry.cast()) },
owner: marker::PhantomData,
},
Shared {
entry: unsafe { crate::mem::raw::Owner::from_raw(this.entry.cast()) },
owner: marker::PhantomData,
},
)
}
}
impl<T, O: crate::depot::raw::PoolOwner<T>, P: crate::depot::raw::PoolPolicy<T, O>, M> Drop
for Unique<'_, T, O, P, M>
{
fn drop(&mut self) {
P::retire(pool::Terminal {
entry: self.entry,
owner: marker::PhantomData,
});
}
}
impl<
'a,
T: crate::mem::raw::Edge,
O: crate::depot::raw::PoolSharing<T>,
P: crate::depot::raw::PoolPolicy<T, O>,
> Shared<'a, T, O, P>
{
pub(crate) fn get(&self) -> &T {
self.entry.get().get()
}
pub fn is_same(&self, other: &Self) -> bool {
self.entry.as_ptr() == other.entry.as_ptr()
}
pub fn try_clone(&self) -> Result<Self, rc::Error> {
Ok(Self {
entry: self.entry.try_clone()?,
owner: marker::PhantomData,
})
}
pub fn try_unique(self) -> Result<Unique<'a, T, O, P>, Self> {
if !self.get().is_unique() {
return Err(self);
}
unsafe { self.get().retire() };
Ok(Unique {
entry: self.entry.into_raw().cast(),
owner: marker::PhantomData,
})
}
}
impl<'owner, T> pool::Unique<'owner, Resident<T>, Header<T>> {
pub fn begin(mut self, value: T) -> pool::Unique<'owner, Resident<T>, Header<T>, Initialized> {
let resident = self.get_mut();
unsafe { resident.value.get().write(mem::MaybeUninit::new(value)) };
unsafe { self.map() }
}
pub fn commit(self, value: T) -> pool::Shared<'owner, Resident<T>, Header<T>, Initialized> {
self.begin(value).freeze()
}
}
impl<T> ops::Deref for pool::Unique<'_, Resident<T>, Header<T>, Initialized> {
type Target = T;
fn deref(&self) -> &Self::Target {
unsafe { (*self.get().value.get()).assume_init_ref() }
}
}
impl<T> ops::DerefMut for pool::Unique<'_, Resident<T>, Header<T>, Initialized> {
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe { (*self.get().value.get()).assume_init_mut() }
}
}
impl<T> ops::Deref for pool::Shared<'_, Resident<T>, Header<T>, Initialized> {
type Target = T;
fn deref(&self) -> &Self::Target {
unsafe { (*self.get().value.get()).assume_init_ref() }
}
}
impl<'owner, T, C> pool::Unique<'owner, T, release::Header<T, C>, release::Notify<'owner>>
where
T: recycle::Recycle + 'owner,
C: release::Context<'owner, T>,
{
pub fn commit(
self,
) -> pool::Unique<'owner, T, release::Header<T, C>, release::Notify<'owner>, release::Frozen>
{
let this = mem::ManuallyDrop::new(self);
Unique {
entry: this.entry,
owner: marker::PhantomData,
}
}
}
impl<'a, T, O: crate::depot::raw::PoolOwner<T>, P: crate::depot::raw::PoolPolicy<T, O>, M>
Unique<'a, T, O, P, M>
{
pub(crate) unsafe fn map<Q: crate::depot::raw::PoolPolicy<T, O>>(
self,
) -> Unique<'a, T, O, Q, M> {
let this = mem::ManuallyDrop::new(self);
Unique {
entry: this.entry,
owner: marker::PhantomData,
}
}
}
#[derive(Debug)]
#[repr(C)]
pub struct Entry<T, O> {
pub(in crate::depot::arena::pool) value: T,
pub(in crate::depot::arena::pool) state: cell::Cell<*mut O>,
}
#[derive(Debug)]
#[repr(transparent)]
pub(in crate::depot) struct Counted<
T: crate::mem::raw::Edge,
O: crate::depot::raw::PoolSharing<T>,
P: crate::depot::raw::PoolPolicy<T, O>,
> {
entry: Entry<T, O>,
policy: marker::PhantomData<fn(P)>,
}
impl<
T: crate::mem::raw::Edge,
O: crate::depot::raw::PoolSharing<T>,
P: crate::depot::raw::PoolPolicy<T, O>,
> Counted<T, O, P>
{
pub(in crate::depot) unsafe fn destroy(pointer: ptr::NonNull<Self>) {
P::retire(Terminal {
entry: pointer.cast(),
owner: marker::PhantomData,
});
}
pub(crate) fn get(&self) -> &T {
&self.entry.value
}
}
pub struct Terminal<'a, T, O: crate::depot::raw::PoolOwner<T>> {
pub(in crate::depot::arena::pool) entry: ptr::NonNull<Entry<T, O>>,
pub(in crate::depot::arena::pool) owner: marker::PhantomData<&'a O>,
}
impl<'a, T, O: crate::depot::raw::PoolOwner<T>> Terminal<'a, T, O> {
pub fn get_mut(&mut self) -> pin::Pin<&mut T> {
unsafe { pin::Pin::new_unchecked(&mut self.entry.as_mut().value) }
}
pub(crate) fn recycle(self) -> &'a O {
let owner = unsafe { &*self.entry.as_ref().state.get() };
unsafe { Entry::recycle(self.entry, owner.free()) };
owner
}
}
impl<T, O> Entry<T, O> {
pub(crate) const fn new(value: T) -> Self {
Self {
value,
state: cell::Cell::new(ptr::null_mut()),
}
}
pub(crate) unsafe fn chain(entries: &mut [Self], free: &cell::Cell<*mut Self>) {
let mut next = free.get();
for entry in entries.iter_mut().rev() {
entry.state.set(next.cast());
next = entry;
}
free.set(next);
}
pub(in crate::depot::arena::pool) unsafe fn recycle(
entry: ptr::NonNull<Self>,
free: &cell::Cell<*mut Self>,
) {
unsafe {
entry
.as_ref()
.state
.set(free.replace(entry.as_ptr()).cast())
};
}
}
unsafe impl<
T: crate::mem::raw::Edge,
O: crate::depot::raw::PoolSharing<T>,
P: crate::depot::raw::PoolPolicy<T, O>,
> crate::mem::raw::Edge for Counted<T, O, P>
{
fn count(&self) -> &crate::mem::raw::Count {
self.entry.value.count()
}
}