use std::fmt;
use std::ops::{Deref, DerefMut, Drop};
use std::sync::Mutex;
pub struct Pool<T> {
stack: Mutex<Vec<T>>,
create: CreateFn<T>,
}
pub type CreateFn<T> = Box<Fn() -> T + Send + Sync>;
#[derive(Debug)]
pub struct PoolGuard<'a, T: 'a> {
pool: &'a Pool<T>,
val: Option<T>,
}
impl<T> Pool<T> {
pub fn new(create: CreateFn<T>) -> Pool<T> {
Pool {
stack: Mutex::new(vec![]),
create: create,
}
}
pub fn get(&self) -> PoolGuard<T> {
let mut stack = self.stack.lock().unwrap();
match stack.pop() {
None => PoolGuard { pool: self, val: Some((self.create)()) },
Some(v) => PoolGuard { pool: self, val: Some(v) },
}
}
fn put(&self, v: T) {
let mut stack = self.stack.lock().unwrap();
stack.push(v);
}
}
impl<'a, T> Deref for PoolGuard<'a, T> {
type Target = T;
fn deref<'b>(&'b self) -> &'b T { self.val.as_ref().unwrap() }
}
impl<'a, T> DerefMut for PoolGuard<'a, T> {
fn deref_mut<'b>(&'b mut self) -> &'b mut T { self.val.as_mut().unwrap() }
}
impl<'a, T> Drop for PoolGuard<'a, T> {
fn drop(&mut self) {
let val = self.val.take().unwrap();
self.pool.put(val);
}
}
impl<T: fmt::Debug> fmt::Debug for Pool<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let stack = self.stack.lock();
let stack = stack.unwrap();
stack.fmt(f)
}
}