use std::sync::Arc;
use std::sync::LazyLock;
use std::sync::Mutex;
use std::sync::MutexGuard;
use linked_hash_map::Entry;
use linked_hash_map::LinkedHashMap;
use super::library::Library;
use super::symbols::Symbols;
const DEFAULT_MAX_CACHE_SIZE: usize = 1 << 30;
static CACHE: LazyLock<Mutex<DebugInfoCache>> = LazyLock::new(|| Mutex::new(DebugInfoCache::new()));
pub struct DebugInfoCache {
cache: LinkedHashMap<u64, Arc<Symbols>>,
size: usize,
max_size: usize,
}
impl DebugInfoCache {
fn new() -> Self {
Self {
cache: Default::default(),
size: 0,
max_size: DEFAULT_MAX_CACHE_SIZE,
}
}
pub fn load(&mut self, library: &Library) -> Result<Arc<Symbols>, anyhow::Error> {
match self.cache.entry(library.inode) {
Entry::Occupied(entry) => Ok(entry.get().clone()),
Entry::Vacant(entry) => {
let symbols = Arc::new(Symbols::load(&library.path)?);
self.size += symbols.bytes_used();
let symbols = entry.insert(symbols).clone();
while self.size > self.max_size {
if let Some((_k, v)) = self.cache.pop_front() {
self.size -= v.bytes_used();
}
}
Ok(symbols)
}
}
}
}
pub fn cache() -> MutexGuard<'static, DebugInfoCache> {
CACHE.lock().expect("lock poisoned")
}