use std::sync::atomic::{
AtomicI64,
Ordering::{Acquire, Release},
};
pub struct WatchVersionMap {
map: Box<[AtomicI64]>,
size_mask: u64,
}
pub const DEFAULT_VERSION_MAP_SIZE: u64 = 1 << 16;
impl Default for WatchVersionMap {
fn default() -> Self {
Self::new(DEFAULT_VERSION_MAP_SIZE)
}
}
impl WatchVersionMap {
pub fn new(size: u64) -> Self {
assert!(
size.is_power_of_two(),
"WatchVersionMap size must be a power of two"
);
let map = (0..size).map(|_| AtomicI64::new(0)).collect::<Box<[_]>>();
Self {
map,
size_mask: size - 1,
}
}
#[inline]
pub fn read_version(&self, key_hash: u64) -> u64 {
unsafe { self.map.get_unchecked((key_hash & self.size_mask) as usize) }.load(Acquire) as u64
}
#[inline]
pub fn increment_version(&self, key_hash: u64) {
unsafe { self.map.get_unchecked((key_hash & self.size_mask) as usize) }.fetch_add(1, Release);
}
}