#![cfg(feature = "random")]
use crate::policy::AdmissionDecision;
use super::CachePolicy;
use parking_lot::Mutex;
use rand::seq::IteratorRandom;
use std::collections::HashMap;
use std::hash::Hash;
#[derive(Debug)]
pub struct RandomPolicy<K> {
items: Mutex<HashMap<K, u64>>,
}
impl<K> RandomPolicy<K> {
pub fn new() -> Self {
Self {
items: Mutex::new(HashMap::new()),
}
}
}
impl<K, V> CachePolicy<K, V> for RandomPolicy<K>
where
K: Eq + Hash + Clone + Send + Sync,
V: Send + Sync,
{
fn on_access(&self, _key: &K, _cost: u64) {}
fn on_admit(&self, key: &K, cost: u64) -> AdmissionDecision<K> {
let mut items = self.items.lock();
items.insert(key.clone(), cost);
AdmissionDecision::Admit }
fn on_remove(&self, key: &K) {
let mut items = self.items.lock();
items.remove(key);
}
fn evict(&self, mut cost_to_free: u64) -> (Vec<K>, u64) {
let mut victims = Vec::new();
let mut total_cost_freed = 0;
let mut items = self.items.lock();
let mut rng = rand::rng();
while cost_to_free > 0 && !items.is_empty() {
let key_to_evict = match items.keys().choose(&mut rng) {
Some(k) => k.clone(),
None => break,
};
if let Some(cost) = items.remove(&key_to_evict) {
cost_to_free = cost_to_free.saturating_sub(cost);
total_cost_freed += cost;
victims.push(key_to_evict);
}
}
(victims, total_cost_freed)
}
fn clear(&self) {
let mut items = self.items.lock();
items.clear();
}
}