|
Boost Users : |
Subject: Re: [Boost-users] Object pools?
From: Ryan McConnehey (mccorywork_at_[hidden])
Date: 2010-02-18 22:13:24
You are correct.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?
The template question had more to do with the operator function having a T*.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?
Why use malloc/free instead of new/delete?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;}
}
};
List only has exactly the number of nodes to hold the items necessary. This means nodes are deleted as objects are handed out and nodes are created as objects are return to the pool. I think using vector would be a better choice since you can reserve memory. This means as objects come and go the memory size of the container remains the same.class Pool : enable_shared_from_this<Pool> {private:
list<buffer_ptr> buffers; // free to use buffers
In my thinking the pool would only contain objects that are the same. What I mean is the asio::buffer's would all be the same size. Nothing wrong with this, I just think if you need different sizes then either have more pools or have the pool be the largest size you need.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
}
Why store shared_ptr's in the list? The asio::buffer's can be created in the constructor and destroyed in the destructor. This would prevent memory leaks. Since the deallocate expects a raw asio::buffer it would be easier to store the raw pointer. What am I missing?
void deallocate(asio::buffer *b) {
this->buffers.push_front(buffer_ptr(b));
}
};
Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net