use std::collections::VecDeque;
use std::sync::Arc;
use dashmap::DashMap;
use mir_codebase::StubSlice;
use parking_lot::Mutex;
pub const DEFAULT_CAPACITY: usize = 6144;
pub struct ParseCache {
map: DashMap<[u8; 32], Arc<StubSlice>>,
order: Mutex<VecDeque<[u8; 32]>>,
capacity: usize,
}
impl Default for ParseCache {
fn default() -> Self {
Self::with_capacity(DEFAULT_CAPACITY)
}
}
impl ParseCache {
pub fn with_capacity(capacity: usize) -> Self {
Self {
map: DashMap::new(),
order: Mutex::new(VecDeque::new()),
capacity: capacity.max(1),
}
}
pub fn get(&self, hash: &[u8; 32]) -> Option<Arc<StubSlice>> {
self.map.get(hash).map(|r| Arc::clone(&*r))
}
pub fn insert(&self, hash: [u8; 32], slice: Arc<StubSlice>) {
let is_new = self.map.insert(hash, slice).is_none();
if !is_new {
return;
}
let mut order = self.order.lock();
order.push_back(hash);
while self.map.len() > self.capacity {
match order.pop_front() {
Some(old) => {
self.map.remove(&old);
}
None => break,
}
}
}
pub fn remove(&self, hash: &[u8; 32]) {
self.map.remove(hash);
}
pub fn len(&self) -> usize {
self.map.len()
}
pub fn is_empty(&self) -> bool {
self.map.is_empty()
}
}