use std::sync::{Arc, RwLock};
use crate::{
estimators::CPDEstimator,
models::Labelled,
types::{Error, Labels, Map, Result, Set},
};
#[derive(Clone, Debug)]
pub struct Cache<'a, C, K, V> {
call: &'a C,
cache: Arc<RwLock<Map<K, V>>>,
}
impl<'a, E, P> Cache<'a, E, (Vec<usize>, Vec<usize>), P>
where
P: Clone,
{
#[inline]
pub fn new(call: &'a E) -> Self {
let cache = Arc::new(RwLock::new(Map::default()));
Self { call, cache }
}
}
impl<C, K, V> Labelled for Cache<'_, C, K, V>
where
C: Labelled,
{
#[inline]
fn labels(&self) -> &Labels {
self.call.labels()
}
}
impl<E, P> CPDEstimator<P> for Cache<'_, E, (Vec<usize>, Vec<usize>), P>
where
E: CPDEstimator<P>,
P: Clone,
{
fn fit(&self, x: &Set<usize>, z: &Set<usize>) -> Result<P> {
let key: (Vec<_>, Vec<_>) = (
x.into_iter().cloned().collect(),
z.into_iter().cloned().collect(),
);
if let Some(value) = self
.cache
.read()
.map_err(|e| Error::Poison(&e.to_string()))?
.get(&key)
{
return Ok(value.clone());
}
let value = self.call.fit(x, z)?;
self.cache
.write()
.map_err(|e| Error::Poison(&e.to_string()))?
.insert(key, value.clone());
Ok(value)
}
}