use std::{cell, mem, ops};
use crate::depot::{self, queue::links};
pub use crate::depot::raw::Node;
pub struct View<'a, T> {
item: &'a Node<T>,
key: links::Index,
}
impl<T> Clone for View<'_, T> {
fn clone(&self) -> Self {
*self
}
}
impl<T> Copy for View<'_, T> {}
impl<T> ops::Deref for View<'_, T> {
type Target = Node<T>;
fn deref(&self) -> &Self::Target {
self.item
}
}
impl<'a, T> View<'a, T> {
pub unsafe fn new(entries: &'a [Node<T>], key: links::Index) -> Self {
let item = unsafe { entries.get_unchecked(key.get()) };
Self { item, key }
}
pub unsafe fn acquire(free: &links::Free, entries: &'a [Node<T>]) -> Option<Self> {
let key = unsafe { depot::raw::Hooks::acquire(entries, free) }?;
Some(unsafe { Self::new(entries, key) })
}
pub fn key(&self) -> &links::Index {
&self.key
}
pub fn into_ref(self) -> &'a Node<T> {
self.item
}
pub fn is_parked(&self) -> bool {
let hook = self.item.hook();
hook.prev_index() == Some(self.key) && hook.next_index() == Some(self.key)
}
pub fn unpark(self) -> Option<links::Detached<'a>> {
self.item.hook().try_unpark(self.key)
}
}
const _: () = {
assert!(mem::size_of::<View<'static, u64>>() == 2 * mem::size_of::<usize>());
assert!(mem::size_of::<Option<View<'static, u64>>>() == 2 * mem::size_of::<usize>());
};
pub struct Entry<T> {
value: cell::Cell<mem::MaybeUninit<T>>,
}
impl<T> Default for Entry<T> {
fn default() -> Self {
Self {
value: cell::Cell::new(mem::MaybeUninit::uninit()),
}
}
}
impl<T> Entry<T> {
pub fn initialize(&self, value: T)
where
T: Copy,
{
self.value.set(mem::MaybeUninit::new(value));
}
pub unsafe fn take(&self) -> T {
unsafe { self.value.replace(mem::MaybeUninit::uninit()).assume_init() }
}
pub unsafe fn retire(&self) {
let mut value = self.value.replace(mem::MaybeUninit::uninit());
unsafe { value.assume_init_drop() };
}
}