use super::*;
use core::fmt::Debug;
use core::hash::Hash;
use hashlink::LruCache;
#[derive(Clone, Debug)]
pub struct AsyncKeyedCache<K, V>
where
K: Hash + Eq + Clone + Debug,
V: Clone,
{
lock_table: AsyncTagLockTable<K>,
cache: Arc<Mutex<LruCache<K, V>>>,
}
impl<K, V> AsyncKeyedCache<K, V>
where
K: Hash + Eq + Clone + Debug,
V: Clone,
{
#[must_use]
pub fn new(capacity: usize) -> Self {
Self {
lock_table: AsyncTagLockTable::new(),
cache: Arc::new(Mutex::new(LruCache::new(capacity))),
}
}
pub async fn lookup(&self, key: K) -> AsyncKeyedCacheEntry<K, V> {
let guard = self.lock_table.lock_tag(key.clone()).await;
AsyncKeyedCacheEntry {
_guard: guard,
cache: self.cache.clone(),
key,
}
}
#[must_use]
pub fn purge(&self) -> bool {
let mut cache = self.cache.lock();
if !self.lock_table.is_empty() {
return false;
}
cache.clear();
true
}
}
pub struct AsyncKeyedCacheEntry<K, V>
where
K: Hash + Eq + Clone + Debug,
V: Clone,
{
_guard: AsyncTagLockGuard<K>,
cache: Arc<Mutex<LruCache<K, V>>>,
key: K,
}
impl<K, V> AsyncKeyedCacheEntry<K, V>
where
K: Hash + Eq + Clone + Debug,
V: Clone,
{
#[must_use]
pub fn key(&self) -> &K {
&self.key
}
#[must_use]
pub fn get(&self) -> Option<V> {
self.cache.lock().get(&self.key).cloned()
}
pub fn insert(&self, value: V) -> Option<V> {
self.cache.lock().insert(self.key.clone(), value)
}
pub fn remove(&self) -> Option<V> {
self.cache.lock().remove(&self.key)
}
}