#![allow(unsafe_code)]
const NIL: u32 = u32::MAX;
struct Node<T> {
item: Option<T>,
next: u32,
}
#[derive(Clone, Copy, Debug)]
pub(crate) struct List {
head: u32,
tail: u32,
len: u32,
}
impl Default for List {
fn default() -> Self {
Self { head: NIL, tail: NIL, len: 0 }
}
}
impl List {
pub(crate) fn len(&self) -> usize {
self.len as usize
}
pub(crate) fn is_empty(&self) -> bool {
self.len == 0
}
}
pub(crate) struct Slab<T> {
nodes: Vec<Node<T>>,
free: u32,
}
impl<T> Slab<T> {
pub(crate) fn with_capacity(capacity: usize) -> Self {
Self { nodes: Vec::with_capacity(capacity), free: NIL }
}
pub(crate) fn capacity(&self) -> usize {
self.nodes.len()
}
#[inline]
unsafe fn node(&self, index: u32) -> &Node<T> {
debug_assert!((index as usize) < self.nodes.len(), "slab read out of range: {index}");
unsafe { self.nodes.get_unchecked(index as usize) }
}
#[inline]
unsafe fn node_mut(&mut self, index: u32) -> &mut Node<T> {
debug_assert!((index as usize) < self.nodes.len(), "slab write out of range: {index}");
unsafe { self.nodes.get_unchecked_mut(index as usize) }
}
fn alloc(&mut self, item: T) -> u32 {
let index = self.free;
if index != NIL {
let node = unsafe { self.node_mut(index) };
let next_free = node.next;
node.item = Some(item);
node.next = NIL;
self.free = next_free;
return index;
}
let index = self.nodes.len() as u32;
assert_ne!(index, NIL, "queue slab exceeded {NIL} live items");
self.nodes.push(Node { item: Some(item), next: NIL });
index
}
pub(crate) fn push_back(&mut self, list: &mut List, item: T) {
let index = self.alloc(item);
if list.tail == NIL {
list.head = index;
} else {
unsafe { self.node_mut(list.tail) }.next = index;
}
list.tail = index;
list.len += 1;
}
pub(crate) fn pop_front(&mut self, list: &mut List) -> Option<T> {
let index = list.head;
if index == NIL {
return None;
}
let free = self.free;
let node = unsafe { self.node_mut(index) };
let item = node.item.take();
let next = node.next;
node.next = free;
self.free = index;
list.head = next;
if next == NIL {
list.tail = NIL;
}
list.len -= 1;
debug_assert!(item.is_some(), "a linked node always holds an item");
item
}
pub(crate) fn front(&self, list: &List) -> Option<&T> {
if list.head == NIL {
return None;
}
unsafe { self.node(list.head) }.item.as_ref()
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::collections::VecDeque;
#[test]
fn each_list_keeps_its_own_fifo_order_while_sharing_one_slab() {
let mut slab = Slab::with_capacity(0);
let mut hot = List::default();
let mut cold = List::default();
for item in 0..6 {
slab.push_back(&mut hot, item);
if item == 3 {
slab.push_back(&mut cold, 100);
}
}
assert_eq!((hot.len(), cold.len()), (6, 1));
assert_eq!(slab.front(&hot), Some(&0));
assert_eq!(slab.front(&cold), Some(&100));
let mut drained = Vec::new();
while let Some(item) = slab.pop_front(&mut hot) {
drained.push(item);
}
assert_eq!(drained, vec![0, 1, 2, 3, 4, 5]);
assert!(hot.is_empty() && slab.front(&hot).is_none());
assert_eq!(slab.pop_front(&mut cold), Some(100));
assert_eq!(slab.pop_front(&mut cold), None);
}
#[test]
fn freed_nodes_are_reused_so_the_slab_tracks_peak_depth_not_throughput() {
let mut slab = Slab::with_capacity(0);
let mut list = List::default();
for item in 0..4 {
slab.push_back(&mut list, item);
}
assert_eq!(slab.capacity(), 4);
for _ in 0..4 {
slab.pop_front(&mut list);
}
for round in 0..10_000 {
slab.push_back(&mut list, round);
assert_eq!(slab.pop_front(&mut list), Some(round));
}
assert_eq!(slab.capacity(), 4);
}
#[test]
fn refilling_an_emptied_list_relinks_both_ends() {
let mut slab = Slab::with_capacity(2);
let mut list = List::default();
slab.push_back(&mut list, 1);
assert_eq!(slab.pop_front(&mut list), Some(1));
assert!(list.is_empty());
slab.push_back(&mut list, 2);
slab.push_back(&mut list, 3);
assert_eq!(list.len(), 2);
assert_eq!(slab.pop_front(&mut list), Some(2));
assert_eq!(slab.pop_front(&mut list), Some(3));
assert_eq!(slab.pop_front(&mut list), None);
}
#[test]
fn randomized_interleaving_matches_independent_reference_queues() {
const LISTS: usize = 8;
let steps = if cfg!(miri) { 2_000 } else { 200_000 };
let mut slab = Slab::with_capacity(0);
let mut lists = [List::default(); LISTS];
let mut model: [VecDeque<u64>; LISTS] = std::array::from_fn(|_| VecDeque::new());
let mut live = 0usize;
let mut peak = 0usize;
let mut state = 0x2545_f491_4f6c_dd1du64;
for step in 0..steps {
state ^= state << 13;
state ^= state >> 7;
state ^= state << 17;
let which = (state >> 3) as usize % LISTS;
if state & 0b11 != 0 {
slab.push_back(&mut lists[which], step);
model[which].push_back(step);
live += 1;
peak = peak.max(live);
} else {
let popped = slab.pop_front(&mut lists[which]);
assert_eq!(popped, model[which].pop_front(), "divergence at step {step}");
live -= usize::from(popped.is_some());
}
assert_eq!(slab.front(&lists[which]), model[which].front());
assert_eq!(lists[which].len(), model[which].len());
}
for (list, reference) in lists.iter_mut().zip(&mut model) {
while let Some(expected) = reference.pop_front() {
assert_eq!(slab.pop_front(list), Some(expected));
}
assert_eq!(slab.pop_front(list), None);
}
assert_eq!(slab.capacity(), peak, "the arena must not exceed peak live depth");
}
}