use crate::clock::{now_ns, pack_deadline, unpack_deadline};
use crate::value::Value;
use std::num::NonZeroU64;
use std::time::Instant;
pub(crate) const WEIGHT_MAX: u32 = u32::MAX;
pub(crate) struct Entry {
pub(crate) value: Value,
pub(crate) expire_at_ns: Option<NonZeroU64>,
pub(crate) weight: u32,
pub(crate) lru_clock: u32,
}
impl Entry {
#[inline]
pub(crate) fn new(value: Value, expire_at: Option<Instant>) -> Self {
Self {
value,
expire_at_ns: expire_at.and_then(pack_deadline),
weight: 0,
lru_clock: 0,
}
}
#[inline]
pub(crate) fn weight(&self) -> u64 {
self.weight as u64
}
#[inline]
pub(crate) fn lru_clock(&self) -> u32 {
self.lru_clock
}
#[inline]
pub(crate) fn set_weight(&mut self, w: u64) {
self.weight = w.min(WEIGHT_MAX as u64) as u32;
}
#[inline]
pub(crate) fn set_lru_clock(&mut self, c: u32) {
self.lru_clock = c;
}
#[inline]
pub(crate) fn add_to_weight(&mut self, delta: i64) {
if delta == 0 {
return;
}
let cur = self.weight as u64;
let new = if delta >= 0 {
cur.saturating_add(delta as u64)
} else {
cur.saturating_sub((-delta) as u64)
};
self.weight = new.min(WEIGHT_MAX as u64) as u32;
}
#[inline]
pub(crate) fn is_expired_at(&self, now: Instant) -> bool {
match self.expire_at_ns {
None => false,
Some(ns) => unpack_deadline(ns) <= now,
}
}
#[inline]
pub(crate) fn is_expired(&self, use_cached: bool, cached_ns: u64) -> bool {
match self.expire_at_ns {
None => false,
Some(d) => d.get() <= if use_cached { cached_ns } else { now_ns() },
}
}
}
const _: () = {
assert!(std::mem::size_of::<Entry>() == 48);
};