#[allow(dead_code)]
use std::rc::Rc;
use std::cell::RefCell;
use std::fmt;
use std::ops::{Drop, Deref, DerefMut};
use std::convert::{AsRef, AsMut};
use std::cmp::{Ord, PartialOrd, PartialEq, Eq, Ordering};
use std::hash::{Hash, Hasher};
use std::borrow::Borrow;
use std::collections::VecDeque;
use std::mem::ManuallyDrop;
use std::ptr;
pub trait Recycleable {
fn new() -> Self;
fn reset(&mut self);
}
pub trait InitializeWith<T> {
fn initialize_with(&mut self, source: T);
}
impl Recycleable for String {
#[inline]
fn new() -> String {
String::new()
}
#[inline]
fn reset(&mut self) {
self.clear();
}
}
impl <T> Recycleable for Vec<T> {
#[inline]
fn new() -> Vec<T> {
Vec::new()
}
#[inline]
fn reset(&mut self) {
self.clear();
}
}
impl <T> Recycleable for VecDeque<T> {
#[inline]
fn new() -> VecDeque<T> {
VecDeque::new()
}
#[inline]
fn reset(&mut self) {
self.clear();
}
}
impl <A> InitializeWith<A> for String where A : AsRef<str> {
#[inline]
fn initialize_with(&mut self, source: A) {
let s : &str = source.as_ref();
self.push_str(s);
}
}
impl <I, T> InitializeWith<I> for Vec<T> where I: Iterator<Item=T>{
#[inline]
fn initialize_with(&mut self, source: I) {
self.extend(source);
}
}
pub struct Recycled<'a, T: 'a> where T: Recycleable {
value: RecycledInner<&'a RefCell<CappedCollection<T>>, T>
}
pub struct RcRecycled<T> where T: Recycleable {
value: RecycledInner<Rc<RefCell<CappedCollection<T>>>, T>
}
macro_rules! impl_recycled {
($name: ident, $typ: ty, $pool: ty) => {
impl <'a, T> AsRef<T> for $typ where T : Recycleable {
fn as_ref(&self) -> &T {
self.value.as_ref()
}
}
impl <'a, T> AsMut<T> for $typ where T : Recycleable {
fn as_mut(&mut self) -> &mut T {
self.value.as_mut()
}
}
impl <'a, T> fmt::Debug for $typ where T : fmt::Debug + Recycleable {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.value.fmt(f)
}
}
impl <'a, T> fmt::Display for $typ where T : fmt::Display + Recycleable {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.value.fmt(f)
}
}
impl <'a, T> PartialEq for $typ where T : PartialEq + Recycleable {
fn eq(&self, other: &Self) -> bool {
self.value.eq(&other.value)
}
}
impl <'a, T> Eq for $typ where T: Eq + Recycleable {}
impl <'a, T> PartialOrd for $typ where T: PartialOrd + Recycleable {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
self.value.partial_cmp(&other.value)
}
}
impl <'a, T> Ord for $typ where T: Ord + Recycleable {
fn cmp(&self, other: &Self) -> Ordering {
self.value.cmp(&other.value)
}
}
impl <'a, T> Hash for $typ where T: Hash + Recycleable {
fn hash<H: Hasher>(&self, state: &mut H) {
self.value.hash(state)
}
}
impl <'a, T> Deref for $typ where T : Recycleable {
type Target = T;
#[inline]
fn deref(&self) -> &T {
self.as_ref()
}
}
impl <'a, T> DerefMut for $typ where T : Recycleable {
#[inline]
fn deref_mut(&mut self) -> &mut T {
self.as_mut()
}
}
impl <'a, T> $typ where T: Recycleable {
fn new(pool: $pool, value: T) -> $typ {
$name { value: RecycledInner::new(pool, value) }
}
#[inline]
fn new_from<A>(pool: $pool, value: T, source: A) -> $typ where T : InitializeWith<A> {
$name { value: RecycledInner::new_from(pool, value, source) }
}
#[inline]
pub fn detach(self) -> T {
self.value.detach()
}
}
}
}
impl_recycled!{ RcRecycled, RcRecycled<T>, Rc<RefCell<CappedCollection<T>>> }
impl_recycled!{ Recycled, Recycled<'a, T>, &'a RefCell<CappedCollection<T>> }
impl <T> Clone for RcRecycled<T> where T: Clone + Recycleable {
fn clone(&self) -> Self {
RcRecycled {
value: self.value.clone()
}
}
}
impl <'a, T> Clone for Recycled<'a, T> where T: Clone + Recycleable {
fn clone(&self) -> Self {
Recycled {
value: self.value.clone()
}
}
}
struct RecycledInner<P, T> where P: Borrow<RefCell<CappedCollection<T>>>, T : Recycleable {
value: ManuallyDrop<T>,
pool: P
}
impl <P, T> PartialEq for RecycledInner<P, T> where P: Borrow<RefCell<CappedCollection<T>>>,
T: PartialEq + Recycleable {
fn eq(&self, other: &Self) -> bool {
self.value.eq(&other.value)
}
}
impl <P, T> Eq for RecycledInner<P, T> where P: Borrow<RefCell<CappedCollection<T>>>,
T: Eq + Recycleable {
}
impl <P, T> PartialOrd for RecycledInner<P, T> where P: Borrow<RefCell<CappedCollection<T>>>,
T: PartialOrd + Recycleable {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
self.value.partial_cmp(&other.value)
}
}
impl <P, T> Ord for RecycledInner<P, T> where P: Borrow<RefCell<CappedCollection<T>>>,
T: Ord + Recycleable {
fn cmp(&self, other: &Self) -> Ordering {
self.value.cmp(&other.value)
}
}
impl <P, T> Hash for RecycledInner<P, T> where P: Borrow<RefCell<CappedCollection<T>>>,
T: Hash + Recycleable {
fn hash<H: Hasher>(&self, state: &mut H) {
self.value.hash(state)
}
}
impl <'a, T> Clone for RecycledInner<&'a RefCell<CappedCollection<T>>, T> where T: Clone + Recycleable {
fn clone(&self) -> Self {
let pool_ref = &*self.pool;
let mut cloned_value = pool_ref.borrow_mut().remove_or_create();
cloned_value.clone_from(&self.value);
RecycledInner {
value: ManuallyDrop::new(cloned_value),
pool: pool_ref
}
}
}
impl <T> Clone for RecycledInner<Rc<RefCell<CappedCollection<T>>>, T> where T: Clone + Recycleable {
fn clone(&self) -> Self {
let pool_ref = self.pool.clone();
let mut cloned_value = pool_ref.borrow_mut().remove_or_create();
cloned_value.clone_from(&self.value);
RecycledInner {
value: ManuallyDrop::new(cloned_value),
pool: pool_ref
}
}
}
impl <P, T> Drop for RecycledInner<P, T> where P: Borrow<RefCell<CappedCollection<T>>>, T : Recycleable {
#[inline]
fn drop(&mut self) {
let value = unsafe {
ptr::read(&self.value as *const ManuallyDrop<T>)
};
let mut value = ManuallyDrop::into_inner(value);
let pool_ref = self.pool.borrow();
if pool_ref.borrow().is_full() {
drop(value);
return;
}
value.reset();
pool_ref.borrow_mut().insert_prepared_value(value);
}
}
impl <P, T> AsRef<T> for RecycledInner<P, T> where P: Borrow<RefCell<CappedCollection<T>>>, T : Recycleable {
fn as_ref(&self) -> &T {
&self.value
}
}
impl <P, T> AsMut<T> for RecycledInner<P, T> where P: Borrow<RefCell<CappedCollection<T>>>, T : Recycleable {
fn as_mut(&mut self) -> &mut T {
&mut self.value
}
}
impl <P, T> fmt::Debug for RecycledInner<P, T> where P: Borrow<RefCell<CappedCollection<T>>>, T : fmt::Debug + Recycleable {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.value.fmt(f)
}
}
impl <P, T> fmt::Display for RecycledInner<P, T> where P: Borrow<RefCell<CappedCollection<T>>>, T : fmt::Display + Recycleable {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.value.fmt(f)
}
}
impl <P, T> Deref for RecycledInner<P, T> where P: Borrow<RefCell<CappedCollection<T>>>, T : Recycleable {
type Target = T;
#[inline]
fn deref(& self) -> &T {
self.as_ref()
}
}
impl <P, T> DerefMut for RecycledInner<P, T> where P: Borrow<RefCell<CappedCollection<T>>>, T : Recycleable {
#[inline]
fn deref_mut(&mut self) -> & mut T {
self.as_mut()
}
}
impl <P, T> RecycledInner<P, T> where P: Borrow<RefCell<CappedCollection<T>>>, T : Recycleable {
#[inline]
fn new(pool: P, value: T) -> RecycledInner<P, T> {
RecycledInner {
value: ManuallyDrop::new(value),
pool
}
}
#[inline]
fn new_from<A>(pool: P, mut value: T, source: A) -> RecycledInner<P, T> where T : InitializeWith<A> {
value.initialize_with(source);
RecycledInner {
value: ManuallyDrop::new(value),
pool
}
}
#[inline]
fn detach(self) -> T {
let value = unsafe {
ptr::read(&self.value as *const ManuallyDrop<T>)
};
let pool = unsafe {
ptr::read(&self.pool as *const P)
};
mem::forget(self);
drop(pool);
ManuallyDrop::into_inner(value)
}
}
struct CappedCollection <T> where T: Recycleable {
values: Vec<T>,
cap: usize,
supplier: Box<dyn Supply<Output=T>>
}
impl <T> CappedCollection <T> where T: Recycleable {
#[inline]
pub fn new(mut supplier: Box<dyn Supply<Output=T>>, starting_size: usize, max_size: usize) -> CappedCollection<T> {
use std::cmp;
let starting_size = cmp::min(starting_size, max_size);
let values: Vec<T> =
(0..starting_size)
.map(|_| supplier.get() )
.collect();
CappedCollection {
values: values,
cap: max_size,
supplier: supplier
}
}
#[inline]
pub fn insert_prepared_value(&mut self, value: T) {
self.values.push(value)
}
#[inline]
pub fn remove(&mut self) -> Option<T> {
self.values.pop()
}
#[inline]
pub fn remove_or_create(&mut self) -> T {
match self.remove() {
Some(value) => value,
None => self.supplier.get()
}
}
#[inline]
pub fn is_full(&self) -> bool {
self.values.len() >= self.cap
}
#[inline]
pub fn len(&self) -> usize {
self.values.len()
}
#[inline]
pub fn cap(&self) -> usize {
self.cap
}
}
pub trait Supply {
type Output: Recycleable;
fn get(&mut self) -> Self::Output;
}
impl <F, T> Supply for F where F: FnMut() -> T, T: Recycleable {
type Output = T;
fn get(&mut self) -> T {
self()
}
}
pub struct Pool <T> where T : Recycleable {
values: Rc<RefCell<CappedCollection<T>>>,
}
impl <T> Pool <T> where T: Recycleable {
#[inline]
pub fn with_size(size: usize) -> Pool <T> {
Pool::with_size_and_max(size, usize::MAX)
}
#[inline]
pub fn with_size_and_max(starting_size: usize, max_size: usize) -> Pool <T> {
let supplier = Box::new(|| T::new());
let values: CappedCollection<T> = CappedCollection::new(supplier, starting_size, max_size);
Pool {
values: Rc::new(RefCell::new(values))
}
}
#[inline]
pub fn size(&self) -> usize {
(*self.values).borrow().len()
}
#[inline]
pub fn max_size(&self) -> usize {
(*self.values).borrow().cap()
}
#[inline]
pub fn new(&self) -> Recycled<T> {
let t = self.detached();
Recycled { value: RecycledInner::new(&*self.values, t) }
}
#[inline(always)]
pub fn new_from<A>(&self, source: A) -> Recycled<T> where T: InitializeWith<A> {
let t = self.detached();
Recycled { value: RecycledInner::new_from(&*self.values, t, source) }
}
#[inline]
pub fn attach(&self, value: T) -> Recycled<T> {
Recycled { value: RecycledInner::new(&*self.values, value) }
}
#[inline]
pub fn detached(&self) -> T {
let mut collection = self.values.borrow_mut();
collection.remove_or_create()
}
#[inline]
pub fn new_rc(&self) -> RcRecycled<T> {
let t = self.detached();
let pool_reference = self.values.clone();
RcRecycled { value: RecycledInner::new(pool_reference, t) }
}
#[inline(always)]
pub fn new_rc_from<A>(&self, source: A) -> RcRecycled<T> where T: InitializeWith<A> {
let t = self.detached();
let pool_reference = self.values.clone();
RcRecycled { value: RecycledInner::new_from(pool_reference, t, source) }
}
#[inline]
pub fn attach_rc(&self, value: T) -> RcRecycled<T> {
let pool_reference = self.values.clone();
RcRecycled { value: RecycledInner::new(pool_reference, value) }
}
}
pub fn pool<T>() -> PoolBuilder<T> where T: Recycleable {
PoolBuilder {
starting_size: 16,
max_size: usize::MAX,
supplier: None
}
}
pub struct PoolBuilder<T> where T: Recycleable {
pub starting_size: usize,
pub max_size: usize,
pub supplier: Option<Box<dyn Supply<Output=T>>>,
}
impl <T> PoolBuilder<T> where T: Recycleable {
pub fn with<U>(self, option_setter: U) -> PoolBuilder<T> where
U: OptionSetter<PoolBuilder<T>> {
option_setter.set_option(self)
}
pub fn build(self) -> Pool<T> where T: Recycleable {
let supplier = self.supplier.unwrap_or(Box::new(|| T::new()));
let values: CappedCollection<T> = CappedCollection::new(supplier, self.starting_size, self.max_size);
Pool {
values: Rc::new(RefCell::new(values))
}
}
}
pub mod settings {
use ::{PoolBuilder, Recycleable, Supply};
pub trait OptionSetter<T> {
fn set_option(self, T) -> T;
}
pub struct StartingSize(pub usize);
pub struct MaxSize(pub usize);
pub struct Supplier<S>(pub S) where S: Supply;
impl <T> OptionSetter<PoolBuilder<T>> for StartingSize where T: Recycleable {
fn set_option(self, mut builder: PoolBuilder<T>) -> PoolBuilder<T> {
let StartingSize(size) = self;
builder.starting_size = size;
builder
}
}
impl <T> OptionSetter<PoolBuilder<T>> for MaxSize where T: Recycleable {
fn set_option(self, mut builder: PoolBuilder<T>) -> PoolBuilder<T> {
let MaxSize(size) = self;
builder.max_size = size;
builder
}
}
impl <T, S> OptionSetter<PoolBuilder<T>> for Supplier<S> where
S: Supply<Output=T> + 'static,
T: Recycleable {
fn set_option(self, mut builder: PoolBuilder<T>) -> PoolBuilder<T> {
let Supplier(supplier) = self;
builder.supplier = Some(Box::new(supplier) as Box<dyn Supply<Output=T>>);
builder
}
}
}
pub use settings::{OptionSetter, StartingSize, MaxSize, Supplier};
use std::mem;