use crate::{Engine, SharedCache};
const RESIDENT_SHARE: usize = 2;
impl SharedCache {
pub fn fit_resident(&self, engines: &[&Engine]) -> Vec<usize> {
if self.memory_capacity() == 0 {
return Vec::new();
}
let sizes: Vec<usize> = engines.iter().map(|e| e.resident_bytes()).collect();
self.fit_resident_bytes(&sizes)
}
pub fn fit_resident_bytes(&self, sizes: &[usize]) -> Vec<usize> {
if self.memory_capacity() == 0 {
return Vec::new();
}
let (held, closing) = within_share(sizes, self.resident_share());
self.set_reserved(held);
closing
}
pub fn resident_share(&self) -> usize {
self.memory_capacity() / RESIDENT_SHARE
}
}
fn within_share(sizes: &[usize], share: usize) -> (usize, Vec<usize>) {
let mut held = 0;
let mut closing = Vec::new();
for (i, &bytes) in sizes.iter().enumerate() {
if i > 0 && bytes > 0 && held + bytes > share {
closing.push(i);
} else {
held += bytes;
}
}
(held, closing)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn beyond_the_share_least_recent_close_first() {
assert_eq!(within_share(&[], 10), (0, vec![]));
assert_eq!(within_share(&[50], 10), (50, vec![]), "the engine in use stays");
assert_eq!(within_share(&[4, 5, 3, 1], 10), (10, vec![2]), "smaller older ones still fit");
assert_eq!(within_share(&[4, 0, 0], 0), (4, vec![]), "nothing resident, nothing closed");
}
}