use std::collections::HashMap;
use std::hash::Hash;
use std::sync::{Arc, RwLock};
#[cfg(test)]
mod tests;
pub trait ValueCache<K: Eq + Hash + Copy + Sync, V: Send + Sync>: Send {
fn get(&self, key: &K) -> Option<Arc<V>>;
fn insert(&self, key: K, value: &Arc<V>);
fn clear(&self);
fn len(&self) -> usize;
fn is_empty(&self) -> bool;
}
struct SimpleCacheEntry<V: Send + Sync> {
value: Arc<V>,
counter: u64,
}
impl<V: Send + Sync> SimpleCacheEntry<V> {
pub fn new(value: &Arc<V>, counter: u64) -> Self {
Self {
value: Arc::clone(value),
counter,
}
}
pub fn get_value(&self) -> Arc<V> {
Arc::clone(&self.value)
}
pub fn counter(&self) -> u64 {
self.counter
}
pub fn set_counter(&mut self, counter: u64) {
self.counter = counter
}
}
pub trait CacheEngine<K: Eq + Hash + Copy + Sync, V: Send + Sync>: Sync {
fn get(&mut self, key: &K) -> Option<Arc<V>>;
fn insert(&mut self, key: K, value: &Arc<V>);
fn clear(&mut self);
fn len(&self) -> usize;
fn is_empty(&self) -> bool;
}
struct SimpleCacheEngine<K: Eq + Hash + Copy + Send + Sync, V: Send + Sync> {
map: HashMap<K, SimpleCacheEntry<V>>,
max_size: usize,
counter: u64,
}
impl<K: Eq + Hash + Copy + Send + Sync, V: Send + Sync> SimpleCacheEngine<K, V> {
pub fn new(max_size: usize) -> Self {
Self {
map: HashMap::new(),
max_size,
counter: 0,
}
}
fn next_counter(&mut self) -> u64 {
let ret = self.counter;
self.counter += 1;
ret
}
fn remove_oldest(&mut self) {
let mut key: Option<K> = None;
let mut oldest = u64::MAX;
for (k, v) in self.map.iter() {
if v.counter() < oldest {
key = Some(*k);
oldest = v.counter()
}
}
if let Some(k) = key {
self.map.remove(&k);
}
}
}
impl<K: Eq + Hash + Copy + Send + Sync, V: Send + Sync> CacheEngine<K, V>
for SimpleCacheEngine<K, V>
{
fn get(&mut self, key: &K) -> Option<Arc<V>> {
let counter = self.next_counter();
let entry = match self.map.get_mut(key) {
Some(entry) => entry,
None => return None,
};
entry.set_counter(counter);
Some(entry.get_value())
}
fn insert(&mut self, key: K, value: &Arc<V>) {
let counter = self.next_counter();
self.map.insert(key, SimpleCacheEntry::new(value, counter));
if self.map.len() > self.max_size {
self.remove_oldest();
}
}
fn clear(&mut self) {
self.map.clear()
}
fn len(&self) -> usize {
self.map.len()
}
fn is_empty(&self) -> bool {
self.map.is_empty()
}
}
pub struct SimpleCache<K: Eq + Hash + Copy + Send + Sync, V: Send + Sync> {
engine: RwLock<SimpleCacheEngine<K, V>>,
}
impl<K: Eq + Hash + Copy + Send + Sync, V: Send + Sync> SimpleCache<K, V> {
pub fn new(max_size: usize) -> Self {
Self {
engine: RwLock::new(SimpleCacheEngine::new(max_size)),
}
}
}
impl<K: Eq + Hash + Copy + Send + Sync, V: Send + Sync> ValueCache<K, V> for SimpleCache<K, V> {
fn get(&self, key: &K) -> Option<Arc<V>> {
let mut s = self.engine.write().unwrap();
s.get(key)
}
fn insert(&self, key: K, value: &Arc<V>) {
let mut s = self.engine.write().unwrap();
s.insert(key, value)
}
fn clear(&self) {
let mut s = self.engine.write().unwrap();
s.clear()
}
fn len(&self) -> usize {
let s = self.engine.read().unwrap();
s.len()
}
fn is_empty(&self) -> bool {
let s = self.engine.read().unwrap();
s.is_empty()
}
}