use std::cell::Cell;
use crate::depot::{
self,
queue::round::{
self,
values::{Head, Slot},
},
};
pub struct Snapshot<'a, T: Copy, const G: usize, P, const N: usize = 0>(
pub(super) round::Snapshot<&'a round::Lanes<Cell<Option<T>>, G, N>, P>,
);
impl<'a, T: Copy, const G: usize, P, const N: usize> Snapshot<'a, T, G, P, N> {
fn filter<const FAIR: bool>(&self, test: impl FnOnce(T) -> bool) -> Option<Head<'a, T, G, N>> {
self.0
.filter::<FAIR>(|head| test(Head(head).get()))
.map(Head)
}
}
impl<'a, T: Copy, const G: usize, const N: usize> Snapshot<'a, T, G, round::Place, N> {
pub fn slot(&self) -> Slot<'a, T, G, N> {
Slot(self.0.slot())
}
pub fn set<R>(&self, test: impl FnOnce(T) -> Option<R>) -> Option<(bool, R)>
where
T: PartialEq,
{
let entry = self.0.slot().get();
let before = entry.get()?;
let result = test(before)?;
if entry.get() != Some(before) {
return None;
}
entry.get()?;
Some((self.0.set(), result))
}
pub fn push(&self, value: T) {
self.0.slot().get().set(Some(value));
self.0.push();
}
}
impl<T: Copy, const G: usize, const N: usize> Snapshot<'_, T, G, round::Front, N> {
pub fn pop_if(self, test: impl FnOnce(T) -> bool) -> Option<T> {
Some(self.filter::<false>(test)?.pop())
}
}
impl<T: Copy, const G: usize, const N: usize> Snapshot<'_, T, G, round::Turn, N> {
pub fn pop_if(self, test: impl FnOnce(T) -> bool) -> Option<T> {
let head = self.filter::<true>(test)?;
Some(Head::consume(unsafe { depot::raw::Proof::new(head) }))
}
}