use parking_lot::Mutex;
use super::{CachedBuf, DEPOT_STRIPE_CAP, DEPOT_STRIPE_MASK, DEPOT_STRIPES, NUM_CLASSES};
use crate::align::CachePadded64;
struct StripeState {
items: Vec<CachedBuf>,
closed: bool,
}
struct DepotStripe {
state: CachePadded64<Mutex<StripeState>>,
}
impl DepotStripe {
const fn new() -> Self {
Self {
state: CachePadded64::new(Mutex::new(StripeState {
items: Vec::new(),
closed: false,
})),
}
}
#[inline]
fn push(&self, buf: CachedBuf) -> bool {
let mut state = self.state.lock();
if state.closed || state.items.len() >= DEPOT_STRIPE_CAP {
return false;
}
state.items.push(buf);
true
}
#[inline]
fn pop(&self) -> Option<CachedBuf> {
self.state.lock().items.pop()
}
#[inline]
fn len(&self) -> usize {
self.state.lock().items.len()
}
fn close(&self, mut on_drop: impl FnMut(CachedBuf)) {
let mut state = self.state.lock();
state.closed = true;
for buf in state.items.drain(..) {
on_drop(buf);
}
}
}
pub(crate) struct Depot {
stripes: [DepotStripe; NUM_CLASSES * DEPOT_STRIPES],
}
impl Depot {
pub(crate) const fn new() -> Self {
Self {
stripes: [const { DepotStripe::new() }; NUM_CLASSES * DEPOT_STRIPES],
}
}
#[inline]
pub(crate) fn push(&self, cls: usize, buf: CachedBuf, tid: u64) -> bool {
self.stripes[cls * DEPOT_STRIPES + ((tid as usize) & DEPOT_STRIPE_MASK)].push(buf)
}
pub(crate) fn pop(&self, cls: usize, tid: u64) -> Option<CachedBuf> {
let base = cls * DEPOT_STRIPES;
let start = (tid as usize) & DEPOT_STRIPE_MASK;
(0..DEPOT_STRIPES).find_map(|i| self.stripes[base + ((start + i) & DEPOT_STRIPE_MASK)].pop())
}
pub(crate) fn total_cached(&self, cls: usize) -> usize {
let base = cls * DEPOT_STRIPES;
(0..DEPOT_STRIPES)
.map(|i| self.stripes[base + i].len())
.sum()
}
pub(crate) fn clear(&self, mut on_drop: impl FnMut(usize, usize)) {
for cls in 0..NUM_CLASSES {
let base = cls * DEPOT_STRIPES;
for stripe in &self.stripes[base..base + DEPOT_STRIPES] {
stripe.close(|buf| on_drop(cls, buf.cap));
}
}
}
}