use std::{cell, mem};
use crate::depot::queue::resident::{self, handoff};
pub type Registry<W, G, L> = resident::Lanes<Entry<W, G>, resident::Parking, L>;
impl<W, G, L> Registry<W, G, L> {
#[must_use = "a drained item remains caller-owned"]
pub fn drain_next(&self) -> Option<W> {
self.draining
.drain(|| Some(self.take::<false>()?.take_value()))
}
}
impl<W, G, const N: usize> Registry<W, G, resident::Fixed<N>> {
pub fn lane<const I: usize>(&self) -> handoff::Lane<'_, W, G, resident::Fixed<N>> {
handoff::Lane {
registry: self,
lane: resident::Lane::new::<N, I>(),
}
}
}
impl<W, G, L> resident::Target for Registry<W, G, L> {
type Key = resident::Key;
fn retire(&self, key: Self::Key) {
if let resident::Removal::Parked(entry) = self.remove(key) {
entry.retire_grant();
}
}
}
union Payload<W, G> {
value: mem::ManuallyDrop<W>,
grant: mem::ManuallyDrop<G>,
}
pub struct Entry<W, G> {
payload: cell::Cell<mem::MaybeUninit<Payload<W, G>>>,
}
impl<W, G> Default for Entry<W, G> {
fn default() -> Self {
Self {
payload: cell::Cell::new(mem::MaybeUninit::uninit()),
}
}
}
impl<W, G> Entry<W, G> {
pub(in crate::depot::queue::resident::handoff) fn write_value(&self, value: W)
where
W: Copy,
{
self.payload.set(mem::MaybeUninit::new(Payload {
value: mem::ManuallyDrop::new(value),
}));
}
pub(in crate::depot::queue::resident::handoff) fn take_value(&self) -> W {
let payload = self.payload.replace(mem::MaybeUninit::uninit());
unsafe { mem::ManuallyDrop::into_inner(payload.assume_init().value) }
}
pub(in crate::depot::queue::resident::handoff) fn write_grant(&self, grant: G) {
self.payload.set(mem::MaybeUninit::new(Payload {
grant: mem::ManuallyDrop::new(grant),
}));
}
pub(in crate::depot::queue::resident::handoff) fn take_grant(&self) -> G {
let payload = self.payload.replace(mem::MaybeUninit::uninit());
unsafe { mem::ManuallyDrop::into_inner(payload.assume_init().grant) }
}
pub(in crate::depot::queue::resident::handoff) fn retire_grant(&self) {
let mut payload = self.payload.replace(mem::MaybeUninit::uninit());
unsafe { mem::ManuallyDrop::drop(&mut payload.assume_init_mut().grant) };
}
}