use std::collections::HashMap;
use std::sync::{Arc, RwLock};
use std::rc::Rc;
use std::cell::RefCell;
use std::any::{Any, TypeId};
use std::ops::{Deref, DerefMut};
use std::fmt;
use std::hash::{Hash, Hasher};
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
#[cfg(test)]
mod tests;
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Config {
pub max: usize,
pub start: usize,
pub step: usize,
}
impl Default for Config {
fn default() -> Self {
Self {
max: 100_000,
start: 1_000,
step: 1_000,
}
}
}
impl fmt::Display for Config {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Config {{max: {}, start: {}, step: {}}})", self.max, self.start, self.step)
}
}
impl Config {
fn next_step(&self, current_capacity: usize) -> Option<usize> {
if current_capacity>=self.max {
return None;
}
let remaining = self.max-current_capacity;
if remaining>=self.step {
return Some(self.step);
} else {
return Some(remaining);
}
}
fn allocate_as_necessary<T>(&self, store: &mut Vec<T>) -> Result<(), ()> {
if store.len()>=self.max {
return Err(()); }
let capacity = store.capacity();
if capacity==store.len() {
if let Some(step) = self.next_step(capacity) {
store.reserve(step);
}
}
Ok(())
}
}
#[derive(Debug)]
pub struct DropGuard<T: Any> {
inner: Option<T>,
pool: Rc<RefCell<PoolInner<Box<dyn Any>>>>,
}
impl<T: Any + Clone> Clone for DropGuard<T> {
fn clone(&self) -> Self {
Self {
inner: Clone::clone(&self.inner),
pool: Rc::clone(&self.pool),
}
}
}
impl<T: Any + PartialEq> PartialEq for DropGuard<T> {
fn eq(&self, other: &DropGuard<T>) -> bool {
self.inner.as_ref().unwrap().eq(other.inner.as_ref().unwrap())
}
}
impl<T: Any + Eq> Eq for DropGuard<T> {}
impl<T: Any + PartialOrd> PartialOrd for DropGuard<T> {
fn partial_cmp(&self, other: &DropGuard<T>) -> Option<std::cmp::Ordering> {
self.inner.as_ref().unwrap().partial_cmp(other.inner.as_ref().unwrap())
}
}
impl<T: Any + Ord> Ord for DropGuard<T> {
fn cmp(&self, other: &DropGuard<T>) -> std::cmp::Ordering {
self.inner.as_ref().unwrap().cmp(other.inner.as_ref().unwrap())
}
}
impl<T: Any + Hash> Hash for DropGuard<T> {
fn hash<H: Hasher>(&self, state: &mut H) {
self.inner.as_ref().unwrap().hash(state);
}
}
impl<T: Any + fmt::Display> fmt::Display for DropGuard<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(self.inner.as_ref().unwrap(), f)
}
}
impl<T: Any> DropGuard<T> {
pub fn new(obj: T, pool: &Pool) -> Self {
let inner = Some(obj);
let pool = Rc::clone(&pool.inner);
Self {
inner,
pool,
}
}
pub fn into_inner(mut guard: DropGuard<T>) -> T {
guard.inner.take().unwrap()
}
}
impl<T: Any> Drop for DropGuard<T> {
fn drop(&mut self) {
if let Some(obj) = self.inner.take() {
let obj = Box::new(obj);
if let Ok(mut pool) = self.pool.try_borrow_mut() {
pool.put::<T>(obj);
}
}
}
}
impl<T: Any> AsRef<T> for DropGuard<T> {
fn as_ref(&self) -> &T {
self.inner.as_ref().unwrap()
}
}
impl<T: Any> AsMut<T> for DropGuard<T> {
fn as_mut(&mut self) -> &mut T {
self.inner.as_mut().unwrap()
}
}
impl<T: Any> Deref for DropGuard<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
self.as_ref()
}
}
impl<T: Any> DerefMut for DropGuard<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
self.as_mut()
}
}
pub struct SyncDropGuard<T: Any + Send + Sync> {
inner: Option<T>,
pool: Arc<RwLock<PoolInner<Box<dyn Any + Send + Sync>>>>,
}
impl<T: Any + Send + Sync + Clone> Clone for SyncDropGuard<T> {
fn clone(&self) -> Self {
Self {
inner: Clone::clone(&self.inner),
pool: Arc::clone(&self.pool),
}
}
}
impl<T: Any + Send + Sync + PartialEq> PartialEq for SyncDropGuard<T> {
fn eq(&self, other: &SyncDropGuard<T>) -> bool {
self.inner.as_ref().unwrap().eq(other.inner.as_ref().unwrap())
}
}
impl<T: Any + Send + Sync + Eq> Eq for SyncDropGuard<T> {}
impl<T: Any + Send + Sync + PartialOrd> PartialOrd for SyncDropGuard<T> {
fn partial_cmp(&self, other: &SyncDropGuard<T>) -> Option<std::cmp::Ordering> {
self.inner.as_ref().unwrap().partial_cmp(other.inner.as_ref().unwrap())
}
}
impl<T: Any + Send + Sync + Ord> Ord for SyncDropGuard<T> {
fn cmp(&self, other: &SyncDropGuard<T>) -> std::cmp::Ordering {
self.inner.as_ref().unwrap().cmp(other.inner.as_ref().unwrap())
}
}
impl<T: Any + Send + Sync + Hash> Hash for SyncDropGuard<T> {
fn hash<H: Hasher>(&self, state: &mut H) {
self.inner.as_ref().unwrap().hash(state);
}
}
impl<T: Any + Send + Sync + fmt::Display> fmt::Display for SyncDropGuard<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(self.inner.as_ref().unwrap(), f)
}
}
impl<T: Any + Send + Sync> SyncDropGuard<T> {
pub fn new(obj: T, pool: &SyncPool) -> Self {
let inner = Some(obj);
let pool = Arc::clone(&pool.inner);
Self {
inner,
pool,
}
}
pub fn into_inner(mut guard: SyncDropGuard<T>) -> T {
guard.inner.take().unwrap()
}
}
impl<T: Any + Send + Sync> Drop for SyncDropGuard<T> {
fn drop(&mut self) {
if let Some(obj) = self.inner.take() {
let obj = Box::new(obj);
if let Ok(mut pool) = self.pool.write() {
pool.put::<T>(obj);
}
}
}
}
impl<T: Any + Send + Sync> AsRef<T> for SyncDropGuard<T> {
fn as_ref(&self) -> &T {
self.inner.as_ref().unwrap()
}
}
impl<T: Any + Send + Sync> AsMut<T> for SyncDropGuard<T> {
fn as_mut(&mut self) -> &mut T {
self.inner.as_mut().unwrap()
}
}
impl<T: Any + Send + Sync> Deref for SyncDropGuard<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
self.as_ref()
}
}
impl<T: Any + Send + Sync> DerefMut for SyncDropGuard<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
self.as_mut()
}
}
#[derive(Debug)]
struct PoolInner<B> {
store: HashMap<TypeId, Vec<B>>,
config: HashMap<TypeId, Config>,
fallback_config: Config,
}
impl<B> Default for PoolInner<B> {
fn default() -> Self {
Self {
store: HashMap::new(),
config: HashMap::new(),
fallback_config: Config::default(),
}
}
}
impl<B> fmt::Display for PoolInner<B> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f, "{{store: {} entries, config: {} entries, fallback_config: {}}}",
self.store.len(), self.config.len(),
self.fallback_config.to_string(),
)
}
}
impl<B> PoolInner<B> {
pub fn get_config<T: Any>(&self) -> Config {
let id = TypeId::of::<T>();
match self.config.get(&id) {
Some(config) => config.clone(),
None => self.fallback_config,
}
}
pub fn fallback_config(&self) -> Config {
self.fallback_config
}
pub fn set_config<T: Any>(&mut self, config: Config) {
let id = TypeId::of::<T>();
self.config.insert(id, config);
}
pub fn delete_config<T: Any>(&mut self) {
let id = TypeId::of::<T>();
self.config.remove(&id);
}
pub fn set_fallback_config(&mut self, config: Config) {
self.fallback_config = config;
}
pub fn get<T: Any>(&mut self) -> Option<B> {
let id = TypeId::of::<T>();
if let Some(list) = self.store.get_mut(&id) {
return list.pop();
}
return None
}
pub fn put<T: Any>(&mut self, boxed_obj: B) {
let id = TypeId::of::<T>();
let config = match self.config.get(&id) {
Some(config) => config,
None => &self.fallback_config,
};
match self.store.get_mut(&id) {
Some(list) => {
if let Ok(_) = config.allocate_as_necessary(list) {
list.push(boxed_obj);
}
}
None => {
let mut list = Vec::<B>::with_capacity(config.start);
list.push(boxed_obj);
self.store.insert(id, list);
}
}
}
}
#[derive(Default)]
pub struct Pool {
pub(crate) inner: Rc<RefCell<PoolInner<Box<dyn Any>>>>,
}
impl Clone for Pool {
fn clone(&self) -> Self {
Self {
inner: Rc::clone(&self.inner),
}
}
}
impl fmt::Display for Pool {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Pool {}", self.inner.borrow().to_string())
}
}
impl Pool {
pub fn new() -> Self {
Self::default()
}
pub fn with_fallback_config(config: Config) -> Self {
let mut pool = Self::default();
pool.set_fallback_config(config);
pool
}
pub fn get_config<T: Any>(&self) -> Config {
self.inner.borrow().get_config::<T>()
}
pub fn fallback_config(&self) -> Config {
self.inner.borrow().fallback_config
}
pub fn set_config<T: Any>(&mut self, config: Config) {
self.inner.borrow_mut().set_config::<T>(config);
}
pub fn delete_config<T: Any>(&mut self) {
self.inner.borrow_mut().delete_config::<T>();
}
pub fn set_fallback_config(&mut self, config: Config) {
self.inner.borrow_mut().fallback_config = config;
}
pub fn get<T: Any>(&mut self) -> Option<T> {
if let Some(boxed_obj) = self.inner.borrow_mut().get::<T>() {
if let Ok(element) = boxed_obj.downcast::<T>() {
return Some(*element);
}
}
None
}
pub fn get_or_default<T: Any + Default>(&mut self) -> T {
match self.get::<T>() {
Some(obj) => {
return obj
}
None => {
return T::default()
}
}
}
pub fn get_with_guard<T: Any>(&mut self) -> Option<DropGuard<T>> {
match self.get::<T>() {
Some(obj) => Some(DropGuard::new(obj, self)),
None => None,
}
}
pub fn get_or_default_with_guard<T: Any + Default>(&mut self) -> DropGuard<T> {
let obj = self.get_or_default::<T>();
DropGuard::new(obj, self)
}
pub fn put<T: Any>(&mut self, obj: T) {
let obj = Box::new(obj);
self.inner.borrow_mut().put::<T>(obj);
}
}
#[derive(Default)]
pub struct SyncPool {
pub(crate) inner: Arc<RwLock<PoolInner<Box<dyn Any + Send + Sync>>>>,
}
impl Clone for SyncPool {
fn clone(&self) -> Self {
Self {
inner: Arc::clone(&self.inner),
}
}
}
impl fmt::Display for SyncPool {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "SyncPool {}", self.inner.read().unwrap().to_string())
}
}
impl SyncPool {
pub fn new() -> Self {
Self::default()
}
pub fn with_fallback_config(config: Config) -> Self {
let mut pool = Self::default();
pool.set_fallback_config(config);
pool
}
pub fn get_config<T: Any + Send + Sync>(&mut self) -> Config {
let inner = self.inner.read().unwrap();
inner.get_config::<T>()
}
pub fn fallback_config(&self) -> Config {
let inner = self.inner.read().unwrap();
inner.fallback_config()
}
pub fn set_config<T: Any + Send + Sync>(&mut self, config: Config) {
let mut inner = self.inner.write().unwrap();
inner.set_config::<T>(config);
}
pub fn delete_config<T: Any>(&mut self) {
let mut inner = self.inner.write().unwrap();
inner.delete_config::<T>();
}
pub fn set_fallback_config(&mut self, config: Config) {
let mut inner = self.inner.write().unwrap();
inner.set_fallback_config(config);
}
pub fn get<T: Any + Send + Sync>(&self) -> Option<T> {
let mut inner = self.inner.write().unwrap();
if let Some(boxed_obj) = inner.get::<T>() {
if let Ok(element) = boxed_obj.downcast::<T>() {
return Some(*element);
}
}
None
}
pub fn get_or_default<T: Any + Send + Sync + Default>(&self) -> T {
match self.get::<T>() {
Some(obj) => {
return obj
}
None => {
return T::default()
}
}
}
pub fn get_with_guard<T: Any + Send + Sync>(&mut self) -> Option<SyncDropGuard<T>> {
match self.get::<T>() {
Some(obj) => Some(SyncDropGuard::new(obj, self)),
None => None,
}
}
pub fn get_or_default_with_guard<T: Any + Send + Sync + Default>(&mut self) -> SyncDropGuard<T> {
let obj = self.get_or_default::<T>();
SyncDropGuard::new(obj, self)
}
pub fn put<T: Any + Send + Sync>(&self, obj: T) {
let obj = Box::new(obj);
let mut inner = self.inner.write().unwrap();
inner.put::<T>(obj);
}
}