2010/2/18 Ryan McConnehey <mccorywork@gmail.com>
 I like your concept for deallocating the object that pool handed out.  I am using a private static class within pool to provide the function to the shared_ptr destructor.  This allowed the object to be delete if the pool was destroyed but causes a bottleneck for other pools of the same type.

As I understand your case is multiple buffers used in async operations in boost::asio.
First: to gain performance, you need some reusable objects pool mechanics to avoid constant allocation/deallocation of memory used by buffers.
Second: buffers must survive pool destruction while being used.
Am I correct?
 
I have two questions.  One, shouldn't the PoolObjectDeleter should be a template class?  

To template or not is totally up to you :) Do you need some generic reusable code(could take some time to develop) or you need fast feature implementation and move further?
 
Two, why is the PoolObjectDeleter passed a shared_ptr<void>?  It seems the pool_mem is to help with reference counting to determine if the pool is destroyed.  Yet, I thought the enable_shared_from_this took care of the reference counting with the pool.lock().

In my sample pool_mem is malloc'ed objects data bodies memory, it would cause undefined behavior if accessed after "free". To avoid that shared_ptr is passed to PoolObjectDeleter. To determine if the pool is destroyed weak_ptr<Pool> is used.

If I'm correct about your case I'd like to post some more code:

typedef shared_ptr<asio::buffer> buffer_ptr;

class PoolBufferDeleter
{
private:
    weak_ptr<Pool> pool;
public:
    PoolBufferDeleter(const shared_ptr<Pool> &p) : pool(p) {}
    void operator()(asio::buffer *buf) {
        shared_ptr<Pool> shared_pool = this->pool.lock();
        if(shared_pool)
            shared_pool->deallocate(buf);
        else {
            free(asio::buffer_cast<void*>(*buf));
            delete buf;
        }
    }
};

class Pool : enable_shared_from_this<Pool> {
private:
    list<buffer_ptr> buffers; // free to use buffers
public:
    buffer_ptr allocate(size_t sz) { // minimal size to use
        for(list<buffer_ptr>::iterator i = this->buffers.begin(); i!= this->buffers.end(); ++i)
            if(asio::buffer_size(*i) >= sz) {
                buffer_ptr ret_value = *i;
                this->buffers.erase(i);
                return ret_value;
            }
                           // malloc is NOT checked!!
        return buffer_ptr(new asio::buffer(malloc(sz), sz), // T *t
                          PoolBufferDeleter(shared_from_this())); // D d
    }

    void deallocate(asio::buffer *b) {
        this->buffers.push_front(buffer_ptr(b));
    }
};


Deleter holds a weak_ptr to pool, so it can determine pool state. It's alive - pass buffer to it, destroy otherwise.