use parking_lot::{Mutex, MutexGuard};
use std::sync::Arc;
#[derive(Debug)]
pub struct ArcCache<K, V: ?Sized> {
cache: Mutex<Option<(K, Arc<V>)>>,
}
impl<K: PartialEq, V: ?Sized> ArcCache<K, V> {
pub const fn new() -> Self {
ArcCache {
cache: Mutex::new(None),
}
}
pub fn get_or_try_insert_with<E>(
&self,
key: K,
factory: impl FnOnce(&K) -> Result<Arc<V>, E>,
) -> Result<Arc<V>, E> {
let mut cache = self.lock();
if let Some((cached_key, value)) = cache.as_ref()
&& *cached_key == key
{
return Ok(Arc::clone(value));
}
*cache = None;
let value = factory(&key)?;
*cache = Some((key, Arc::clone(&value)));
Ok(value)
}
pub fn clear(&self) {
self.lock().take();
}
fn lock(&self) -> MutexGuard<'_, Option<(K, Arc<V>)>> {
self.cache.lock()
}
}
impl<K: PartialEq, T: ?Sized> Default for ArcCache<K, T> {
fn default() -> Self {
Self::new()
}
}