use crate::task::timer::TimerHandle;
use crate::time;
use std::sync::atomic::{AtomicU64, Ordering};
use std::sync::Arc;
use std::time::Duration;
#[derive(Debug)]
pub(crate) struct CacheEntry<V> {
pub(crate) value: Arc<V>,
cost: u64,
pub(crate) expires_at: AtomicU64,
pub(crate) last_accessed: AtomicU64,
pub(crate) ttl_timer_handle: Option<TimerHandle>, pub(crate) tti_timer_handle: Option<TimerHandle>,
}
impl<V> CacheEntry<V> {
pub(crate) fn new(value: V, cost: u64, ttl: Option<Duration>, tti: Option<Duration>) -> Self {
let now = time::now_duration().as_nanos() as u64;
let expires_at = ttl.map_or(0, |d| now + d.as_nanos() as u64);
let last_accessed = tti.map_or(0, |_| now);
Self {
value: Arc::new(value),
cost,
expires_at: AtomicU64::new(expires_at),
last_accessed: AtomicU64::new(last_accessed),
ttl_timer_handle: None,
tti_timer_handle: None,
}
}
pub(crate) fn new_with_expiry(
value: V,
cost: u64,
expires_at: Option<Duration>, tti: Option<Duration>,
) -> Self {
let expires_at_nanos = expires_at.map_or(0, |d| d.as_nanos() as u64);
let last_accessed_nanos = tti.map_or(0, |_| time::now_duration().as_nanos() as u64);
Self {
value: Arc::new(value),
cost,
expires_at: AtomicU64::new(expires_at_nanos),
last_accessed: AtomicU64::new(last_accessed_nanos),
ttl_timer_handle: None,
tti_timer_handle: None,
}
}
pub(crate) fn new_with_custom_expiry(
value: V,
cost: u64,
expires_at: u64, tti: Option<Duration>,
) -> Self {
let last_accessed = tti.map_or(0, |_| time::now_duration().as_nanos() as u64);
Self {
value: Arc::new(value),
cost,
expires_at: AtomicU64::new(expires_at),
last_accessed: AtomicU64::new(last_accessed),
ttl_timer_handle: None,
tti_timer_handle: None,
}
}
pub(crate) fn new_with_cost(value: Arc<V>, cost: u64) -> Self {
Self {
value,
cost,
expires_at: AtomicU64::new(0),
last_accessed: AtomicU64::new(0),
ttl_timer_handle: None,
tti_timer_handle: None,
}
}
#[inline]
pub(crate) fn value(&self) -> Arc<V> {
self.value.clone()
}
#[inline]
pub(crate) fn cost(&self) -> u64 {
self.cost
}
#[inline]
pub(crate) fn update_last_accessed(&self) {
self
.last_accessed
.store(time::now_duration().as_nanos() as u64, Ordering::Relaxed);
}
#[inline]
pub(crate) fn is_expired(&self, tti: Option<Duration>) -> bool {
let now_nanos = time::now_duration().as_nanos() as u64;
let expires_at = self.expires_at.load(Ordering::Relaxed);
if expires_at > 0 && now_nanos >= expires_at {
return true;
}
if let Some(time_to_idle) = tti {
let last_accessed = self.last_accessed.load(Ordering::Relaxed);
if now_nanos >= last_accessed + time_to_idle.as_nanos() as u64 {
return true;
}
}
false
}
pub(crate) fn set_timer_handles(
&mut self,
ttl_handle: Option<TimerHandle>,
tti_handle: Option<TimerHandle>,
) {
self.ttl_timer_handle = ttl_handle;
self.tti_timer_handle = tti_handle;
}
}