use foundation::TokenId;
use crate::kv_prefix::KvPrefix;
pub(crate) struct SessionSlot {
pub(crate) kv: gpu::KvCacheManager,
pub(crate) gdn: Option<gpu::GdnStateManager>,
pub(crate) kv_prefix: KvPrefix,
pub(crate) last_used: u64,
}
pub(crate) struct SessionPool {
slots: Vec<SessionSlot>,
clock: u64,
}
impl SessionPool {
pub(crate) fn new(slots: Vec<SessionSlot>) -> Self {
Self { slots, clock: 0 }
}
pub(crate) fn empty() -> Self {
Self::new(Vec::new())
}
pub(crate) fn capacity(&self) -> usize {
self.slots.len()
}
pub(crate) fn best_match(&self, prompt_ids: &[TokenId]) -> Option<(usize, usize)> {
best_scoring_index(
self.slots
.iter()
.map(|slot| slot.kv_prefix.common_prefix(prompt_ids)),
)
}
pub(crate) fn take(&mut self, idx: usize) -> SessionSlot {
self.slots.remove(idx)
}
pub(crate) fn take_lru(&mut self) -> SessionSlot {
let idx = lru_index(self.slots.iter().map(|slot| slot.last_used))
.expect("take_lru called on an empty pool");
self.slots.remove(idx)
}
pub(crate) fn park(&mut self, mut slot: SessionSlot) {
self.clock += 1;
slot.last_used = self.clock;
self.slots.push(slot);
}
}
fn best_scoring_index(scores: impl Iterator<Item = usize>) -> Option<(usize, usize)> {
scores
.enumerate()
.max_by_key(|&(_, score)| score)
.filter(|&(_, score)| score > 0)
}
fn lru_index(ticks: impl Iterator<Item = u64>) -> Option<usize> {
ticks
.enumerate()
.min_by_key(|&(_, tick)| tick)
.map(|(idx, _)| idx)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn the_highest_score_wins() {
assert_eq!(best_scoring_index([3, 5, 2].into_iter()), Some((1, 5)));
}
#[test]
fn an_empty_iterator_never_scores() {
assert_eq!(best_scoring_index(std::iter::empty()), None);
}
#[test]
fn an_all_zero_pool_offers_no_match() {
assert_eq!(best_scoring_index([0, 0, 0].into_iter()), None);
}
#[test]
fn a_lone_nonzero_score_wins_at_its_own_value() {
assert_eq!(best_scoring_index([0, 7, 0].into_iter()), Some((1, 7)));
}
#[test]
fn the_oldest_tick_is_evicted() {
assert_eq!(lru_index([5, 1, 3].into_iter()), Some(1));
}
#[test]
fn an_empty_pool_has_no_lru() {
assert_eq!(lru_index(std::iter::empty()), None);
}
}