use super::BlockId;
#[derive(Debug)]
pub struct ThreadLocalCounters {
local: Vec<u64>,
flush_threshold: usize,
blocks_since_flush: usize,
flush_count: usize,
}
impl ThreadLocalCounters {
#[must_use]
pub fn new(block_count: usize) -> Self {
Self {
local: vec![0; block_count],
flush_threshold: 1000,
blocks_since_flush: 0,
flush_count: 0,
}
}
#[must_use]
pub fn with_flush_threshold(block_count: usize, threshold: usize) -> Self {
Self {
local: vec![0; block_count],
flush_threshold: threshold,
blocks_since_flush: 0,
flush_count: 0,
}
}
#[inline(always)]
pub fn increment(&mut self, block: BlockId) {
let idx = block.as_u32() as usize;
if idx < self.local.len() {
self.local[idx] += 1;
self.blocks_since_flush += 1;
if self.blocks_since_flush >= self.flush_threshold {
self.internal_flush();
}
}
}
#[inline]
#[must_use]
pub fn get(&self, block: BlockId) -> u64 {
let idx = block.as_u32() as usize;
self.local.get(idx).copied().unwrap_or(0)
}
#[must_use]
pub fn flush(&mut self) -> Vec<u64> {
let result = self.local.clone();
self.local.fill(0);
self.blocks_since_flush = 0;
self.flush_count += 1;
result
}
fn internal_flush(&mut self) {
self.blocks_since_flush = 0;
self.flush_count += 1;
}
#[must_use]
pub fn flush_count(&self) -> usize {
self.flush_count
}
#[must_use]
pub fn block_count(&self) -> usize {
self.local.len()
}
#[must_use]
pub fn has_pending(&self) -> bool {
self.blocks_since_flush > 0
}
#[must_use]
pub fn flush_threshold(&self) -> usize {
self.flush_threshold
}
}
impl Default for ThreadLocalCounters {
fn default() -> Self {
Self::new(0)
}
}