История изменений
Исправление derlafff, (текущая версия) :
Писал похожий по сути код. Уверен, в нем есть куча проблем и в целом неадеквата, но он хотя бы конпелируется.
use async_lock::Mutex;
use std::collections::HashMap;
use std::hash::Hash;
use std::sync::Arc;
use std::time::{Duration, Instant};
pub(crate) struct Cache<K: Eq + Hash, V: Default> {
lru: Mutex<HashMap<K, Entry<V>>>,
ttl: Duration,
max_size: usize,
}
struct Entry<T: Default> {
used: Instant,
value: Arc<T>,
}
impl<K: Eq + Hash, V: Default> Cache<K, V> {
pub fn new(max_size: usize, ttl: Duration) -> Self {
let lru = Mutex::new(HashMap::with_capacity(max_size));
Cache { lru, max_size, ttl }
}
pub async fn get(&self, key: K) -> Arc<V> {
let mut g = self.lru.lock().await;
let entry = g.entry(key).or_insert_with(|| Entry {
used: Instant::now(),
value: Arc::new(V::default()),
});
// TODO: avoid double-setting this field?
entry.used = Instant::now();
entry.value.clone()
}
pub async fn clean(&self) {
// удолил: для этого топика не важно.
// если интересно, смотрите в истории
}
}
Исправление derlafff, :
Писал похожий по сути код. Уверен, в нем есть куча проблем и в целом неадеквата, но он хотя бы конпелируется.
use async_lock::Mutex;
use std::collections::HashMap;
use std::hash::Hash;
use std::sync::Arc;
use std::time::{Duration, Instant};
// Cache does two things:
// stores items in a cache
// makes sure two parallel requests are never executed
pub(crate) struct Cache<K: Eq + Hash, V: Default> {
lru: Mutex<HashMap<K, Entry<V>>>,
ttl: Duration,
max_size: usize,
}
struct Entry<T: Default> {
used: Instant,
value: Arc<T>,
}
impl<K: Eq + Hash, V: Default> Cache<K, V> {
pub fn new(max_size: usize, ttl: Duration) -> Self {
let lru = Mutex::new(HashMap::with_capacity(max_size));
Cache { lru, max_size, ttl }
}
pub async fn get(&self, key: K) -> Arc<V> {
let mut g = self.lru.lock().await;
// get or default ASAP - we are blocking everyone else
let entry = g.entry(key).or_insert_with(|| Entry {
used: Instant::now(),
value: Arc::new(V::default()),
});
// TODO: avoid double-setting this field?
entry.used = Instant::now();
entry.value.clone()
}
pub async fn clean(&self) {
// удолил: для этого топика не важно.
// если интересно, смотрите в истории
}
}
Исправление derlafff, :
Писал похожий по сути код. Уверен, в нем есть куча проблем и в целом неадеквата, но он хотя бы конпелируется.
use async_lock::Mutex;
use std::collections::HashMap;
use std::hash::Hash;
use std::sync::Arc;
use std::time::{Duration, Instant};
// Cache does two things:
// stores items in a cache
// makes sure two parallel requests are never executed
pub(crate) struct Cache<K: Eq + Hash, V: Default> {
lru: Mutex<HashMap<K, Entry<V>>>,
ttl: Duration,
max_size: usize,
}
struct Entry<T: Default> {
used: Instant,
value: Arc<T>,
}
impl<K: Eq + Hash, V: Default> Cache<K, V> {
pub fn new(max_size: usize, ttl: Duration) -> Self {
let lru = Mutex::new(HashMap::with_capacity(max_size));
Cache { lru, max_size, ttl }
}
pub async fn get(&self, key: K) -> Arc<V> {
let mut g = self.lru.lock().await;
// get or default ASAP - we are blocking everyone else
let entry = g.entry(key).or_insert_with(|| Entry {
used: Instant::now(),
value: Arc::new(V::default()),
});
// TODO: avoid double-setting this field?
entry.used = Instant::now();
entry.value.clone()
}
pub async fn clean(&self) {
let mut g = self.lru.lock().await;
// check if we need to do anything at all
if g.len() <= self.max_size {
return;
}
// at this point it should be safe to substract unsigned ints
let mut to_remove = self.max_size - g.len();
// remove all entries which exceed ttl
g.retain(|_k, v| {
if to_remove == 0 || v.used.elapsed() < self.ttl {
false
} else {
to_remove -= 1;
true
}
});
// TODO: implement max_size
}
}
Исходная версия derlafff, :
Писал похожий по сути код. Уверен, в нем есть куча проблем и в целом неадеквата, но он хотя бы конпелируется.
use async_lock::Mutex;
use std::collections::HashMap;
use std::hash::Hash;
use std::sync::Arc;
use std::time::{Duration, Instant};
// Cache does two things:
// stores items in a cache
// makes sure two parallel requests are never executed
pub(crate) struct Cache<K: Eq + Hash, V: Default> {
lru: Mutex<HashMap<K, Entry<V>>>,
ttl: Duration,
max_size: usize,
}
struct Entry<T: Default> {
used: Instant,
value: Arc<T>,
}
impl<K: Eq + Hash, V: Default> Cache<K, V> {
pub fn new(max_size: usize, ttl: Duration) -> Self {
let lru = Mutex::new(HashMap::with_capacity(max_size));
Cache { lru, max_size, ttl }
}
pub async fn get(&self, key: K) -> Arc<V> {
let mut g = self.lru.lock().await;
// get or default ASAP - we are blocking everyone else
let entry = g.entry(key).or_insert_with(|| Entry {
used: Instant::now(),
value: Arc::new(V::default()),
});
// TODO: avoid double-setting this field?
entry.used = Instant::now();
entry.value.clone()
}
pub async fn clean(&self) {
let mut g = self.lru.lock().await;
// check if we need to do anything at all
if g.len() <= self.max_size {
return;
}
// at this point it should be safe to substract unsigned ints
let mut to_remove = self.max_size - g.len();
// remove all entries which exceed ttl
g.retain(|_k, v| {
if to_remove == 0 || v.used.elapsed() < self.ttl {
false
} else {
to_remove -= 1;
true
}
});
// TODO: implement max_size
}
}