use std::fmt::Debug;
use blink_alloc::Blink;
use crate::common::defaults::POOL_KEEP_LIMIT;
use crate::common::types::ScoreType;
use parking_lot::Mutex;
pub struct SearchScratchPool {
pool: Mutex<Vec<(SearchScratchScores, Blink)>>,
}
impl Debug for SearchScratchPool {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("SearchScratchPool").finish_non_exhaustive()
}
}
impl SearchScratchPool {
#[expect(clippy::new_without_default)]
pub fn new() -> SearchScratchPool {
SearchScratchPool {
pool: Mutex::new(Vec::with_capacity(*POOL_KEEP_LIMIT)),
}
}
pub fn get(&self) -> SearchScratch<'_> {
let (scores, arena) = self.pool.lock().pop().unwrap_or_default();
SearchScratch {
pool: self,
scores,
arena,
}
}
}
pub struct SearchScratch<'a> {
pool: &'a SearchScratchPool,
pub(crate) scores: SearchScratchScores,
pub(crate) arena: Blink,
}
impl SearchScratch<'_> {
#[cfg(test)]
pub fn new_for_test() -> SearchScratch<'static> {
use std::sync::OnceLock;
static POOL: OnceLock<SearchScratchPool> = OnceLock::new();
POOL.get_or_init(SearchScratchPool::new).get()
}
}
type SearchScratchScores = Vec<ScoreType>;
impl Drop for SearchScratch<'_> {
fn drop(&mut self) {
let SearchScratch {
pool: SearchScratchPool { pool },
scores,
arena,
} = self;
let mut pool = pool.lock();
if pool.len() < *POOL_KEEP_LIMIT {
let scores = std::mem::take(scores);
let mut arena = std::mem::take(arena);
arena.reset();
pool.push((scores, arena));
}
}
}