use super::state_f64::StateF64;
#[derive(Debug)]
pub struct StatePoolF64 {
pool: Vec<StateF64>,
allocations: usize,
reuses: usize,
}
impl StatePoolF64 {
const MAX_POOL_SIZE: usize = 32;
const INITIAL_CAPACITY: usize = 16;
pub fn new() -> Self {
const PREWARM_SIZE: usize = 4;
let mut pool = Vec::with_capacity(Self::INITIAL_CAPACITY);
for _ in 0..PREWARM_SIZE {
pool.push(StateF64::new());
}
Self {
pool,
allocations: PREWARM_SIZE, reuses: 0,
}
}
#[inline]
pub fn acquire(&mut self) -> StateF64 {
if let Some(mut state) = self.pool.pop() {
state.clear();
self.reuses += 1;
state
} else {
self.allocations += 1;
StateF64::new()
}
}
#[inline]
pub fn release(&mut self, state: StateF64) {
if self.pool.len() < Self::MAX_POOL_SIZE {
self.pool.push(state);
}
}
pub fn pool_size(&self) -> usize {
self.pool.len()
}
pub fn total_allocations(&self) -> usize {
self.allocations
}
pub fn total_reuses(&self) -> usize {
self.reuses
}
pub fn reuse_rate(&self) -> f64 {
let total_acquires = self.allocations + self.reuses;
if total_acquires == 0 {
0.0
} else {
self.reuses as f64 / total_acquires as f64
}
}
}
impl Default for StatePoolF64 {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::transducer::{Algorithm, PositionF64};
#[test]
fn test_pool_new() {
let pool = StatePoolF64::new();
assert_eq!(pool.pool_size(), 4);
assert_eq!(pool.total_allocations(), 4);
assert_eq!(pool.total_reuses(), 0);
}
#[test]
fn test_pool_acquire_reuses_when_available() {
let mut pool = StatePoolF64::new();
let state = pool.acquire();
assert!(state.is_empty());
assert_eq!(pool.total_reuses(), 1);
pool.release(state);
assert_eq!(pool.pool_size(), 4);
let state2 = pool.acquire();
assert!(state2.is_empty());
assert_eq!(pool.total_reuses(), 2);
}
#[test]
fn test_pool_release_clears_state() {
let mut pool = StatePoolF64::new();
let query_length = 4;
let mut state = pool.acquire();
state.insert(PositionF64::new(1, 0.0), Algorithm::Standard, query_length);
assert_eq!(state.len(), 1);
pool.release(state);
let state2 = pool.acquire();
assert!(state2.is_empty());
}
#[test]
fn test_pool_respects_max_size() {
let mut pool = StatePoolF64::new();
for _ in 0..StatePoolF64::MAX_POOL_SIZE {
pool.release(StateF64::new());
}
assert_eq!(pool.pool_size(), StatePoolF64::MAX_POOL_SIZE);
pool.release(StateF64::new());
assert_eq!(pool.pool_size(), StatePoolF64::MAX_POOL_SIZE);
}
#[test]
fn test_pool_reuse_rate() {
let mut pool = StatePoolF64::new();
assert_eq!(pool.reuse_rate(), 0.0);
let state1 = pool.acquire();
pool.release(state1);
let _state2 = pool.acquire();
let expected = 2.0 / 6.0;
assert!((pool.reuse_rate() - expected).abs() < 1e-6);
}
}