use core::{
fmt::Debug,
ops::Deref,
};
use std::num::NonZeroUsize;
use crate::{
prelude::*,
support::concurrency::threads::{
resolve_max_pool,
unstable_current_thread_id_hash,
},
};
pub struct PoolToy<T>
where
T: Send,
{
pool: Vec<T>,
}
impl<T> Deref for PoolToy<T>
where
T: Send,
{
type Target = T;
fn deref(&self) -> &Self::Target {
self.get()
}
}
impl<T> AsRef<T> for PoolToy<T>
where
T: Send,
{
fn as_ref(&self) -> &T {
self.get()
}
}
impl<T> PoolToy<T>
where
T: Clone + Send,
{
pub fn new(
item: T,
max_pool: Option<NonZeroUsize>,
) -> Self {
let max_pool = resolve_max_pool(max_pool);
Self::from_pool(vec![item; max_pool])
}
}
impl<T> PoolToy<T>
where
T: Send,
{
pub fn from_pool(pool: Vec<T>) -> Self {
assert!(!pool.is_empty());
Self { pool }
}
pub fn get(&self) -> &T {
let tid = unstable_current_thread_id_hash();
&self.pool[tid % self.pool.len()]
}
pub fn len(&self) -> usize {
self.pool.len()
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
}
impl<T> Clone for PoolToy<T>
where
T: Clone + Send,
{
fn clone(&self) -> Self {
Self {
pool: self.pool.clone(),
}
}
}
impl<T> Debug for PoolToy<T>
where
T: Send + Debug,
{
fn fmt(
&self,
f: &mut core::fmt::Formatter<'_>,
) -> core::fmt::Result {
f.debug_struct("PoolToy")
.field("item", &self.pool[0])
.field("len", &self.pool.len())
.finish()
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::support::concurrency::threads::resolve_max_pool;
#[test]
fn test_pool_toy() {
let max_pool = Some(NonZeroUsize::new(128).unwrap());
let pool = PoolToy::new(10, max_pool);
assert!(!pool.is_empty());
let size = resolve_max_pool(max_pool);
assert_eq!(pool.len(), size);
assert_eq!(&pool.pool, vec![10; size].as_slice());
assert_eq!(pool.get(), &10);
assert_eq!(pool.as_ref(), &10);
assert_eq!(*pool, 10);
assert_eq!(
format!("{:?}", pool),
format!("PoolToy {{ item: 10, len: {size} }}")
);
let clone = pool.clone();
assert_eq!(&clone.pool, &pool.pool);
}
}