use std::sync::{
atomic::{AtomicIsize, Ordering},
OnceLock,
};
use super::CachePadded;
pub struct Counter(Box<[CachePadded<AtomicIsize>]>);
impl Default for Counter {
fn default() -> Counter {
static CPUS: OnceLock<usize> = OnceLock::new();
let num_cpus = *CPUS.get_or_init(|| {
std::thread::available_parallelism()
.map(Into::into)
.unwrap_or(1)
});
let shards = (0..num_cpus.next_power_of_two())
.map(|_| Default::default())
.collect();
Counter(shards)
}
}
impl Counter {
#[inline]
pub fn get(&self, guard: &impl seize::Guard) -> &AtomicIsize {
let shard = guard.thread_id() & (self.0.len() - 1);
&self.0[shard].value
}
#[inline]
pub fn sum(&self) -> usize {
self.0
.iter()
.map(|x| x.value.load(Ordering::Relaxed))
.sum::<isize>()
.try_into()
.unwrap_or(0)
}
}