use crate::{init, Pool, Recyclable};
use thread_local::CachedThreadLocal;
pub fn builder<T>() -> PoolBuilder<T>
where
T: Recyclable,
{
PoolBuilder::default()
}
pub type Supplier<T> = dyn Fn() -> T + Send + Sync;
pub struct PoolBuilder<T: Recyclable> {
pub(crate) starting_size: usize,
pub(crate) supplier: Option<Box<Supplier<T>>>,
}
impl<T> PoolBuilder<T>
where
T: Recyclable,
{
pub fn with_starting_size(mut self, starting_size: usize) -> Self {
self.starting_size = starting_size;
self
}
pub fn with_supplier<S>(mut self, supplier: S) -> Self
where
S: Fn() -> T + Send + Sync + 'static,
{
self.supplier = Some(Box::new(supplier));
self
}
pub fn build(self) -> Pool<T> {
let values = CachedThreadLocal::new();
for _ in 0..self.starting_size {
if let Some(supplier) = self.supplier.as_ref() {
values.get_or(|| init()).borrow_mut().push(supplier())
} else {
values.get_or(|| init()).borrow_mut().push(T::new())
}
}
Pool {
values,
settings: self,
}
}
pub fn build_with(self, items: Vec<T>) -> Pool<T> {
let values = CachedThreadLocal::new();
let size = items.len();
for itm in items {
values.get_or(|| init()).borrow_mut().push(itm);
}
if size < self.starting_size {
let remainder = self.starting_size - size;
for _ in 0..remainder {
if let Some(supplier) = self.supplier.as_ref() {
values.get_or(|| init()).borrow_mut().push(supplier())
} else {
values.get_or(|| init()).borrow_mut().push(T::new())
}
}
}
Pool {
values,
settings: self,
}
}
}
impl<T> Default for PoolBuilder<T>
where
T: Recyclable,
{
fn default() -> Self {
Self {
starting_size: 0,
supplier: None,
}
}
}