use std::cell::RefCell;
pub(crate) struct DeferredQueue<T> {
items: RefCell<Vec<T>>,
}
impl<T> Default for DeferredQueue<T> {
fn default() -> Self {
Self::new()
}
}
impl<T> DeferredQueue<T> {
pub(crate) const fn new() -> Self {
Self {
items: RefCell::new(Vec::new()),
}
}
pub(crate) fn push(&self, item: T) {
self.items.borrow_mut().push(item);
crate::jobs::wake_loop();
}
pub(crate) fn drain(&self) -> Vec<T> {
std::mem::take(&mut *self.items.borrow_mut())
}
pub(crate) fn peek<U>(&self, f: impl FnOnce(&[T]) -> U) -> U {
f(&self.items.borrow())
}
#[cfg(test)]
pub(crate) fn is_empty(&self) -> bool {
self.items.borrow().is_empty()
}
pub(crate) fn clear(&self) {
self.items.borrow_mut().clear();
}
}
pub(crate) struct DeferredSlot<T> {
item: RefCell<Option<T>>,
}
impl<T> Default for DeferredSlot<T> {
fn default() -> Self {
Self {
item: RefCell::new(None),
}
}
}
impl<T> DeferredSlot<T> {
pub(crate) fn set(&self, value: T) {
*self.item.borrow_mut() = Some(value);
crate::jobs::wake_loop();
}
pub(crate) fn take(&self) -> Option<T> {
self.item.borrow_mut().take()
}
#[cfg(test)]
pub(crate) fn is_empty(&self) -> bool {
self.item.borrow().is_none()
}
pub(crate) fn clear(&self) {
*self.item.borrow_mut() = None;
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn a_queue_accumulates_and_a_slot_keeps_the_last() {
let queue: DeferredQueue<u8> = DeferredQueue::new();
assert!(queue.is_empty());
queue.push(1);
queue.push(2);
assert!(!queue.is_empty());
assert_eq!(queue.drain(), vec![1, 2], "a queue owes every item");
assert!(queue.is_empty(), "and is ready for the next batch");
let slot: DeferredSlot<u8> = DeferredSlot::default();
assert!(slot.is_empty());
slot.set(1);
slot.set(2);
assert_eq!(
slot.take(),
Some(2),
"a slot owes the answer, not the history"
);
assert!(slot.is_empty());
}
}