mempool 0.3.1

A fast thread safe memory pool for reusing allocations.
Documentation
extern crate crossbeam;
extern crate syncbox;
extern crate test;

use std::cell::RefCell;
use std::sync::Mutex;

use self::crossbeam::sync::{MsQueue, SegQueue, TreiberStack};
use self::syncbox::ArrayQueue;
use self::test::{Bencher, black_box};

use {CreateFn, Pool};

#[derive(Debug)]
struct Dummy(usize);

fn dummy() -> CreateFn<Box<Dummy>> {
    use std::sync::atomic::AtomicUsize;
    use std::sync::atomic::Ordering::SeqCst;

    let count = AtomicUsize::new(0);
    Box::new(move || {
        Box::new(Dummy(count.fetch_add(1, SeqCst)))
    })
}

#[bench]
fn mutex_lock_unlock(b: &mut Bencher) {
    let lock = Mutex::new(());
    b.iter(|| {
        black_box({
            let lock = lock.lock().unwrap();
            drop(lock);
        })
    });
}

#[bench]
fn mempool_get_put_tls(b: &mut Bencher) {
    let pool = Pool::new(dummy());
    let _ = pool.get();
    b.iter(|| {
        black_box({
            let data = pool.get();
            drop(data);
        })
    });
}

#[bench]
fn refcell_get_put(b: &mut Bencher) {
    let pool = PoolRefCell::new(dummy());
    let _ = pool.get();
    b.iter(|| {
        black_box({
            let data = pool.get();
            drop(data);
        })
    });
}

#[bench]
fn mutex_get_put(b: &mut Bencher) {
    let pool = PoolMutex::new(dummy());
    let _ = pool.get();
    b.iter(|| {
        black_box({
            let data = pool.get();
            drop(data);
        })
    });
}

#[bench]
fn mpmc_get_put(b: &mut Bencher) {
    let pool = PoolMpmc::new(dummy());
    let _ = pool.get();
    b.iter(|| {
        black_box({
            let data = pool.get();
            drop(data);
        })
    });
}

#[bench]
fn crossbeam_treiber_get_put(b: &mut Bencher) {
    let pool = PoolTreiber::new(dummy());
    let _ = pool.get();
    b.iter(|| {
        black_box({
            let data = pool.get();
            drop(data);
        })
    });
}

#[bench]
fn crossbeam_ms_get_put(b: &mut Bencher) {
    let pool = PoolMs::new(dummy());
    let _ = pool.get();
    b.iter(|| {
        black_box({
            let data = pool.get();
            drop(data);
        })
    });
}

#[bench]
fn crossbeam_seg_get_put(b: &mut Bencher) {
    let pool = PoolSeg::new(dummy());
    let _ = pool.get();
    b.iter(|| {
        black_box({
            let data = pool.get();
            drop(data);
        })
    });
}

struct PoolRefCell<T> {
    stack: RefCell<Vec<T>>,
    create: CreateFn<T>,
}

struct PoolRefCellGuard<'a, T: 'a> {
    pool: &'a PoolRefCell<T>,
    data: Option<T>,
}

impl<T> PoolRefCell<T> {
    fn new(create: CreateFn<T>) -> PoolRefCell<T> {
        PoolRefCell { stack: RefCell::new(vec![]), create: create }
    }

    fn get(&self) -> PoolRefCellGuard<T> {
        let mut stack = self.stack.borrow_mut();
        match stack.pop() {
            None => {
                PoolRefCellGuard { pool: self, data: Some((self.create)()) }
            }
            Some(data) => PoolRefCellGuard { pool: self, data: Some(data) }
        }
    }

    fn put(&self, data: T) {
        let mut stack = self.stack.borrow_mut();
        stack.push(data);
    }
}

impl<'a, T> Drop for PoolRefCellGuard<'a, T> {
    fn drop(&mut self) {
        let data = self.data.take().unwrap();
        self.pool.put(data);
    }
}

struct PoolMutex<T> {
    stack: Mutex<Vec<T>>,
    create: CreateFn<T>,
}

struct PoolMutexGuard<'a, T: 'a> {
    pool: &'a PoolMutex<T>,
    data: Option<T>,
}

impl<T> PoolMutex<T> {
    fn new(create: CreateFn<T>) -> PoolMutex<T> {
        PoolMutex { stack: Mutex::new(vec![]), create: create }
    }

    fn get(&self) -> PoolMutexGuard<T> {
        let mut stack = self.stack.lock().unwrap();
        match stack.pop() {
            None => {
                PoolMutexGuard { pool: self, data: Some((self.create)()) }
            }
            Some(data) => PoolMutexGuard { pool: self, data: Some(data) }
        }
    }

    fn put(&self, data: T) {
        let mut stack = self.stack.lock().unwrap();
        stack.push(data);
    }
}

impl<'a, T> Drop for PoolMutexGuard<'a, T> {
    fn drop(&mut self) {
        let data = self.data.take().unwrap();
        self.pool.put(data);
    }
}

struct PoolMpmc<T: Send + 'static> {
    stack: ArrayQueue<T>,
    create: CreateFn<T>,
}

struct PoolMpmcGuard<'a, T: Send + 'static> {
    pool: &'a PoolMpmc<T>,
    data: Option<T>,
}

impl<T: Send + 'static> PoolMpmc<T> {
    fn new(create: CreateFn<T>) -> PoolMpmc<T> {
        PoolMpmc { stack: ArrayQueue::with_capacity(1), create: create }
    }

    fn get(&self) -> PoolMpmcGuard<T> {
        match self.stack.pop() {
            None => {
                PoolMpmcGuard { pool: self, data: Some((self.create)()) }
            }
            Some(data) => PoolMpmcGuard { pool: self, data: Some(data) }
        }
    }

    fn put(&self, data: T) {
        let _ = self.stack.push(data);
    }
}

impl<'a, T: Send + 'static> Drop for PoolMpmcGuard<'a, T> {
    fn drop(&mut self) {
        let data = self.data.take().unwrap();
        self.pool.put(data);
    }
}

struct PoolTreiber<T> {
    stack: TreiberStack<T>,
    create: CreateFn<T>,
}

struct PoolTreiberGuard<'a, T: 'a> {
    pool: &'a PoolTreiber<T>,
    data: Option<T>,
}

impl<T> PoolTreiber<T> {
    fn new(create: CreateFn<T>) -> PoolTreiber<T> {
        PoolTreiber { stack: TreiberStack::new(), create: create }
    }

    fn get(&self) -> PoolTreiberGuard<T> {
        match self.stack.pop() {
            None => {
                PoolTreiberGuard { pool: self, data: Some((self.create)()) }
            }
            Some(data) => PoolTreiberGuard { pool: self, data: Some(data) }
        }
    }

    fn put(&self, data: T) {
        self.stack.push(data);
    }
}

impl<'a, T> Drop for PoolTreiberGuard<'a, T> {
    fn drop(&mut self) {
        let data = self.data.take().unwrap();
        self.pool.put(data);
    }
}

struct PoolMs<T> {
    stack: MsQueue<T>,
    create: CreateFn<T>,
}

struct PoolMsGuard<'a, T: 'a> {
    pool: &'a PoolMs<T>,
    data: Option<T>,
}

impl<T> PoolMs<T> {
    fn new(create: CreateFn<T>) -> PoolMs<T> {
        PoolMs { stack: MsQueue::new(), create: create }
    }

    fn get(&self) -> PoolMsGuard<T> {
        match self.stack.try_pop() {
            None => {
                PoolMsGuard { pool: self, data: Some((self.create)()) }
            }
            Some(data) => PoolMsGuard { pool: self, data: Some(data) }
        }
    }

    fn put(&self, data: T) {
        self.stack.push(data);
    }
}

impl<'a, T> Drop for PoolMsGuard<'a, T> {
    fn drop(&mut self) {
        let data = self.data.take().unwrap();
        self.pool.put(data);
    }
}

struct PoolSeg<T> {
    stack: SegQueue<T>,
    create: CreateFn<T>,
}

struct PoolSegGuard<'a, T: 'a> {
    pool: &'a PoolSeg<T>,
    data: Option<T>,
}

impl<T> PoolSeg<T> {
    fn new(create: CreateFn<T>) -> PoolSeg<T> {
        PoolSeg { stack: SegQueue::new(), create: create }
    }

    fn get(&self) -> PoolSegGuard<T> {
        match self.stack.try_pop() {
            None => {
                PoolSegGuard { pool: self, data: Some((self.create)()) }
            }
            Some(data) => PoolSegGuard { pool: self, data: Some(data) }
        }
    }

    fn put(&self, data: T) {
        self.stack.push(data);
    }
}

impl<'a, T> Drop for PoolSegGuard<'a, T> {
    fn drop(&mut self) {
        let data = self.data.take().unwrap();
        self.pool.put(data);
    }
}