use std::borrow::Cow;
use std::collections::hash_map::RandomState;
use std::fmt::Debug;
use std::hash::{BuildHasher, Hash};
use std::path::{Path, PathBuf};
use std::sync::{Arc, Mutex};
use crate::global::GlobalPool;
use crate::pool::{Pool, PoolKindSealed, Poolable};
use crate::{PoolKind, Pooled};
pub type SharedString<S = RandomState> = Pooled<SharedPool<String, S>, S>;
pub type SharedPath<S = RandomState> = Pooled<SharedPool<PathBuf, S>, S>;
pub type SharedBuffer<S = RandomState> = Pooled<SharedPool<Vec<u8>, S>, S>;
pub type StringPool<S = RandomState> = SharedPool<String, S>;
pub type PathPool<S = RandomState> = SharedPool<PathBuf, S>;
pub type BufferPool<S = RandomState> = SharedPool<Vec<u8>, S>;
#[derive(Debug)]
pub struct SharedPool<T, S = RandomState>(Arc<Mutex<Pool<Self, S>>>)
where
T: Poolable + Debug + Clone + Eq + PartialEq + Hash + Ord + PartialOrd,
S: BuildHasher;
impl<T, S> SharedPool<T, S>
where
T: Poolable + Debug + Clone + Eq + PartialEq + Hash + Ord + PartialOrd,
S: BuildHasher,
{
#[must_use]
pub fn pooled<C>(&self) -> C
where
C: FromIterator<Pooled<Self, S>>,
{
self.with_active_symbols(|pool| {
pool.active
.iter()
.map(|data| Pooled(data.clone()))
.collect()
})
}
}
impl<S> SharedPool<String, S>
where
S: BuildHasher,
{
#[must_use]
pub fn with_hasher(hasher: S) -> Self {
Self::with_capacity_and_hasher(0, hasher)
}
#[must_use]
pub fn with_capacity_and_hasher(initial_capacity: usize, hasher: S) -> Self {
Self(Arc::new(Mutex::new(Pool::with_capacity_and_hasher(
initial_capacity,
hasher,
))))
}
#[must_use]
pub fn get<'a, V>(&self, value: V) -> SharedString<S>
where
V: Into<Cow<'a, str>>,
{
let value = value.into();
self.with_active_symbols(|symbols| symbols.get(value, self))
}
}
impl<S> SharedPool<PathBuf, S>
where
S: BuildHasher,
{
#[must_use]
pub fn get<'a, V>(&self, value: V) -> SharedPath<S>
where
V: Into<Cow<'a, Path>>,
{
let value = value.into();
self.with_active_symbols(|symbols| symbols.get(value, self))
}
}
impl<S> SharedPool<Vec<u8>, S>
where
S: BuildHasher,
{
#[must_use]
pub fn get<'a, V>(&self, value: V) -> SharedBuffer<S>
where
V: Into<Cow<'a, [u8]>>,
{
let value = value.into();
self.with_active_symbols(|symbols| symbols.get(value, self))
}
}
impl<T, S> Clone for SharedPool<T, S>
where
T: Poolable + Debug + Clone + Eq + PartialEq + Hash + Ord + PartialOrd,
S: BuildHasher,
{
fn clone(&self) -> Self {
Self(self.0.clone())
}
}
impl<T, S> PoolKind<S> for SharedPool<T, S>
where
T: Poolable + Debug + Clone + Eq + PartialEq + Hash + Ord + PartialOrd,
S: BuildHasher,
{
}
impl<T, S> PoolKindSealed<S> for SharedPool<T, S>
where
T: Poolable + Debug + Clone + Eq + PartialEq + Hash + Ord + PartialOrd,
S: BuildHasher,
{
type Owned = T;
type Pooled = T::Boxed;
fn with_active_symbols<R>(&self, logic: impl FnOnce(&mut Pool<Self, S>) -> R) -> R {
let mut symbols = self.0.lock().expect("poisoned");
logic(&mut symbols)
}
fn address_of(&self) -> *const () {
Arc::as_ptr(&self.0).cast()
}
}
impl<T, S> PartialEq for SharedPool<T, S>
where
T: Poolable + Debug + Clone + Eq + PartialEq + Hash + Ord + PartialOrd,
S: BuildHasher,
{
fn eq(&self, other: &SharedPool<T, S>) -> bool {
Arc::ptr_eq(&self.0, &other.0)
}
}
impl<T, S, S2> PartialEq<&'static GlobalPool<T, S2>> for SharedPool<T, S>
where
T: Poolable + Debug + Clone + Eq + PartialEq + Hash + Ord + PartialOrd,
S: BuildHasher,
S2: BuildHasher,
{
fn eq(&self, _other: &&'static GlobalPool<T, S2>) -> bool {
false
}
}
impl<T, S, S2> PartialEq<SharedPool<T, S>> for &'static GlobalPool<T, S2>
where
T: Poolable + Debug + Clone + Eq + PartialEq + Hash + Ord + PartialOrd,
S: BuildHasher,
S2: BuildHasher,
{
fn eq(&self, _other: &SharedPool<T, S>) -> bool {
false
}
}
impl<T> Default for SharedPool<T, RandomState>
where
T: Poolable + Debug + Clone + Eq + PartialEq + Hash + Ord + PartialOrd,
{
fn default() -> Self {
Self(Arc::default())
}
}