use crate::{
depot,
depot::queue::{links, round::phase},
};
#[derive(Debug)]
pub struct Join<'a, H: ?Sized, L: ?Sized> {
pub hooks: &'a H,
pub lanes: &'a L,
pub entries: &'a links::Chain,
pub active: &'a links::Cycle,
pub index: links::Index,
}
impl<'a, H: depot::raw::Hooks + ?Sized, L: depot::raw::Hooks + ?Sized> Join<'a, H, L> {
pub fn insert(source: depot::raw::Proof<(Self, links::Index), phase::Vacant>) {
let (lane, index) = source.into_inner();
let vacant = unsafe { links::Detached::new(lane.hooks.hook_raw(index), index) };
Self::push(unsafe { depot::raw::Proof::new((lane, vacant)) });
}
pub fn push(source: depot::raw::Proof<(Self, links::Detached<'a>), phase::Vacant>) {
let (lane, vacant) = source.into_inner();
let activate = lane.entries.is_empty();
unsafe { vacant.push(lane.entries, lane.hooks) };
if activate {
unsafe { lane.active.push(lane.lanes, lane.index) };
}
}
pub fn remove(
source: depot::raw::Proof<(Self, links::Index), phase::Linked>,
) -> links::Detached<'a> {
let (lane, index) = source.into_inner();
let vacant = unsafe { lane.entries.unlink(lane.hooks, index) };
if lane.entries.is_empty() {
unsafe { lane.active.unlink_key(lane.lanes, lane.index) };
}
vacant
}
pub fn pop(source: depot::raw::Proof<Self, phase::Ready>) -> Option<links::Detached<'a>> {
let lane = source.into_inner();
let index = lane.entries.first()?;
Some(unsafe { lane.remove_front::<false, false>(index) })
}
pub fn active<const ROTATE: bool>(
source: depot::raw::Proof<Self, phase::Active>,
) -> links::Detached<'a> {
let source = Self::front(source);
let (lane, index) = source.into_inner();
unsafe { lane.remove_front::<true, ROTATE>(index) }
}
pub fn front(
source: depot::raw::Proof<Self, phase::Active>,
) -> depot::raw::Proof<(Self, links::Index), phase::Head> {
let lane = source.into_inner();
let index = unsafe { lane.entries.front_key() };
unsafe { depot::raw::Proof::new((lane, index)) }
}
pub fn head<const ROTATE: bool>(
source: depot::raw::Proof<(Self, links::Index), phase::Head>,
) -> links::Detached<'a> {
let (lane, index) = source.into_inner();
unsafe { lane.remove_front::<false, ROTATE>(index) }
}
unsafe fn remove_front<const ACTIVE: bool, const ROTATE: bool>(
self,
index: links::Index,
) -> links::Detached<'a> {
let change = unsafe { depot::raw::Pop::at(self.entries, self.hooks, index) };
let (_, next) = change.edge().links();
let vacant = depot::raw::Removal::commit(change);
if next == links::Index::END {
if ACTIVE {
unsafe { self.active.pop_front(self.lanes, self.index) };
} else {
unsafe { self.active.unlink_key(self.lanes, self.index) };
}
} else if ROTATE {
let first = if ACTIVE {
self.index
} else {
unsafe { self.active.first_live() }
};
unsafe {
self.active
.move_back::<_, ACTIVE>(self.lanes, self.index, first)
};
}
vacant
}
}