use std::sync::atomic::{AtomicU64, Ordering};
use std::sync::{Arc, Mutex, Weak};
use crate::config::BudgetConfig;
use crate::jemalloc::JemallocStatsSource;
use crate::policy::{CacheView, Policy};
use crate::reporter::NonCacheReporter;
use crate::resizable::Resizable;
use crate::rss::RssSource;
pub(crate) struct BudgetState {
pub(super) config: BudgetConfig,
pub(super) registrations: Mutex<Vec<Registration>>,
pub(super) active_lease_bytes: AtomicU64,
pub(super) previous_cache_bytes: AtomicU64,
pub(super) previous_cache_count: AtomicU64,
pub(super) previous_rss_bytes: AtomicU64,
pub(super) verdict_streak: Mutex<VerdictStreak>,
pub(super) policy: Box<dyn Policy>,
pub(super) rss: Box<dyn RssSource>,
pub(super) jemalloc: Box<dyn JemallocStatsSource>,
pub(super) reporters: Mutex<Vec<Weak<dyn NonCacheReporter>>>,
#[cfg(feature = "heap-profiling")]
pub(super) heap_profiler: Option<crate::heap_profile::HeapProfiler>,
}
impl BudgetState {
pub(crate) fn release_lease(&self, bytes: u64) {
let mut current = self.active_lease_bytes.load(Ordering::Relaxed);
loop {
let next = current
.checked_sub(bytes)
.expect("memory reservation release exceeds outstanding bytes");
match self.active_lease_bytes.compare_exchange(
current,
next,
Ordering::Relaxed,
Ordering::Relaxed,
) {
Ok(_) => return,
Err(observed) => current = observed,
}
}
}
}
#[derive(Clone, Copy, Debug, Default)]
pub(super) struct VerdictStreak {
pub(super) label: &'static str,
pub(super) length: u32,
}
pub(super) struct Registration {
pub(super) cache: Weak<dyn Resizable>,
pub(super) preferred_max_bytes: u64,
}
pub(super) struct LiveViews {
pub(super) views: Vec<CacheView>,
pub(super) live_caches: Vec<Arc<dyn Resizable>>,
}