use std::sync::Arc;
use crate::cache::{BoundedStore, CacheCategory, CacheCounters, CacheEvent};
use crate::projection::draft::SourceFragment;
use super::claim::SourceKey;
pub(crate) struct ProjectionStore {
counters: Arc<CacheCounters>,
entries: BoundedStore<SourceKey, Arc<SourceFragment>>,
}
impl ProjectionStore {
pub(crate) fn new(ceiling: u32, counters: Arc<CacheCounters>) -> Self {
Self {
counters,
entries: BoundedStore::new(ceiling),
}
}
pub(crate) fn unretained() -> Self {
Self::new(0, Arc::new(CacheCounters::default()))
}
pub(crate) fn reused(
&mut self,
key: &SourceKey,
states: impl Fn(&SourceFragment) -> bool,
) -> Option<Arc<SourceFragment>> {
match self.entries.selected(key, |held| states(held)) {
Some(retained) => {
self.counters
.record(CacheCategory::SourceProjection, CacheEvent::Hit, 1);
Some(retained)
}
None => {
self.counters
.record(CacheCategory::SourceProjection, CacheEvent::Miss, 1);
None
}
}
}
pub(crate) fn retain(
&mut self,
key: SourceKey,
derived: SourceFragment,
) -> Arc<SourceFragment> {
let shared = Arc::new(derived);
let evicted = self.entries.retain(key, Arc::clone(&shared));
self.counters.record(
CacheCategory::SourceProjection,
CacheEvent::Eviction,
evicted,
);
shared
}
pub(crate) fn clear(&mut self) {
self.entries.clear();
}
}