use crate::config::PoolConfig;
use crate::error::Result;
use crate::handle::OwnedHandle;
use crate::pool::FixedPool;
use std::marker::PhantomData;
pub struct ThreadLocalPool<T> {
pool: FixedPool<T>,
_marker: PhantomData<*const ()>, }
impl<T: crate::traits::Poolable> ThreadLocalPool<T> {
pub fn new(capacity: usize) -> Result<Self> {
let config = PoolConfig::builder().capacity(capacity).build()?;
Self::with_config(config)
}
pub fn with_config(config: PoolConfig<T>) -> Result<Self> {
Ok(Self {
pool: FixedPool::with_config(config)?,
_marker: PhantomData,
})
}
pub fn allocate(&self, value: T) -> Result<OwnedHandle<'_, T>> {
self.pool.allocate(value)
}
#[inline]
pub fn capacity(&self) -> usize {
self.pool.capacity()
}
#[inline]
pub fn available(&self) -> usize {
self.pool.available()
}
#[inline]
pub fn allocated(&self) -> usize {
self.pool.allocated()
}
#[inline]
pub fn is_full(&self) -> bool {
self.pool.is_full()
}
#[inline]
pub fn is_empty(&self) -> bool {
self.pool.is_empty()
}
}
unsafe impl<T: Send> Send for ThreadLocalPool<T> {}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn thread_local_pool_basic() {
let pool = ThreadLocalPool::<i32>::new(10).unwrap();
let handle = pool.allocate(42).unwrap();
assert_eq!(*handle, 42);
assert_eq!(pool.allocated(), 1);
drop(handle);
assert_eq!(pool.allocated(), 0);
}
#[test]
fn thread_local_pool_multiple_allocations() {
let pool = ThreadLocalPool::new(5).unwrap();
let _h1 = pool.allocate(1).unwrap();
let _h2 = pool.allocate(2).unwrap();
let _h3 = pool.allocate(3).unwrap();
assert_eq!(pool.allocated(), 3);
assert_eq!(pool.available(), 2);
}
#[test]
fn thread_local_pool_capacity() {
let pool = ThreadLocalPool::<i32>::new(3).unwrap();
let _h1 = pool.allocate(1).unwrap();
let _h2 = pool.allocate(2).unwrap();
let _h3 = pool.allocate(3).unwrap();
assert!(pool.is_full());
let result = pool.allocate(4);
assert!(result.is_err());
}
}