use std::{marker, mem, ptr};
use crate::depot::{
self,
arena::linked::{self, fifo, fifo::ends, slots},
};
#[must_use = "an initialized slot must be published or released"]
pub struct Live<T, H: linked::Source<T>, Tag = ()> {
pub(super) vacant: slots::Vacant<T, H, Tag>,
}
impl<T, H: linked::Source<T>, Tag> Live<T, H, Tag> {
pub(crate) unsafe fn detached(owner: H, index: slots::Index<Tag>) -> Self {
Self {
vacant: slots::Vacant {
owner,
index,
value: marker::PhantomData,
},
}
}
pub fn get(&self) -> &T {
unsafe { self.vacant.owner.store().value(self.vacant.index) }
}
pub(crate) fn take(self) -> (T, slots::Vacant<T, H, Tag>) {
let this = mem::ManuallyDrop::new(self);
let node = unsafe { this.vacant.owner.store().slot(this.vacant.index.raw()) };
let value = unsafe { (&*node.value.get()).assume_init_read() };
node.next.set(this.vacant.index.raw());
(value, unsafe { ptr::read(&this.vacant) })
}
pub(crate) const fn index(&self) -> slots::Index<Tag> {
self.vacant.index
}
pub(crate) unsafe fn owner_mut(&mut self) -> &mut H {
&mut self.vacant.owner
}
pub(crate) unsafe fn publish(self) -> H {
let this = mem::ManuallyDrop::new(self);
unsafe { ptr::read(&this.vacant.owner) }
}
}
impl<T, H: linked::Source<T>, Tag> Drop for Live<T, H, Tag> {
fn drop(&mut self) {
let index = self.vacant.index.raw();
let node = unsafe { self.vacant.owner.store().slot(index) };
unsafe { (&mut *node.value.get()).assume_init_drop() };
}
}
impl<T, Tag> Live<T, &slots::Store<T>, Tag> {
pub(crate) unsafe fn append(self, links: &mut ends::Exclusive<slots::Index<Tag>>) {
let mut claim = self;
let index = claim.index();
unsafe { links.append_end(claim.owner_mut(), index) };
unsafe { claim.publish() };
}
pub(crate) unsafe fn prepend(self, links: &mut ends::Exclusive<slots::Index<Tag>>) {
let mut claim = self;
let index = claim.index();
unsafe { links.prepend_link(claim.owner_mut(), index) };
unsafe { claim.publish() };
}
pub fn push_back(proof: depot::raw::Proof<(Self, &mut fifo::Fifo<Tag>), linked::Same>) {
let (claim, state) = proof.into_inner();
unsafe { state.state.append(claim) };
}
}