use parking_lot::{RwLock, RwLockReadGuard, RwLockUpgradableReadGuard};
use crate::shard_reader::ShardReader;
use crate::shard_write::ShardWrite;
use crate::sym::Sym;
pub(crate) type ShardReadGuard<'a> = RwLockReadGuard<'a, ShardWrite>;
#[repr(align(128))]
pub(crate) struct Shard {
state: RwLock<ShardWrite>,
}
impl Shard {
pub(crate) fn with_capacity(strings: usize, bytes: usize) -> Self {
Self {
state: RwLock::new(ShardWrite::with_capacity(strings, bytes)),
}
}
#[inline]
pub(crate) fn len(&self) -> usize {
self.state.read().len()
}
#[inline]
pub(crate) fn intern<R: Fn(&[u8]) -> u64>(&self, idx: usize, h: u64, s: &str, rehash: &R) -> Sym {
let up = self.state.upgradable_read();
if let Some(sym) = up.get(h, s) {
return sym;
}
let mut w = RwLockUpgradableReadGuard::upgrade(up);
w.insert_new(idx, h, s, rehash)
}
#[inline]
pub(crate) fn intern_bytes<R: Fn(&[u8]) -> u64>(
&self,
idx: usize,
h: u64,
bytes: &[u8],
rehash: &R,
) -> Result<Sym, core::str::Utf8Error> {
let up = self.state.upgradable_read();
if let Some(sym) = up.get_bytes(h, bytes) {
return Ok(sym);
}
let s = core::str::from_utf8(bytes)?;
let mut w = RwLockUpgradableReadGuard::upgrade(up);
Ok(w.insert_new(idx, h, s, rehash))
}
#[inline]
pub(crate) fn get(&self, h: u64, s: &str) -> Option<Sym> {
self.state.read().get(h, s)
}
pub(crate) fn freeze(self) -> ShardReader {
let (offsets, bytes) = self.state.into_inner().into_parts();
ShardReader::new(offsets.into_boxed_slice(), bytes.into_boxed_slice())
}
pub(crate) fn read_guard(&self) -> ShardReadGuard<'_> {
self.state.read()
}
pub(crate) fn snapshot_locked(guard: &ShardReadGuard<'_>) -> ShardReader {
let (offsets, bytes) = guard.parts();
ShardReader::new(offsets.to_vec().into_boxed_slice(), bytes.to_vec().into_boxed_slice())
}
#[cfg(test)]
pub(crate) fn capacities(&self) -> (usize, usize, usize) {
self.state.read().capacities()
}
}