Re: [Boost-users] Object pools?
Hi, of course, in my opinion pool has to manage objects life time. However sharing objects with pool owner by shared ptr seems to be a good idea, because pool still manages objects life time. Using shared pointer also inside pool solves the problem, maybe. It is correct?
----- Reply message -----
Da: "Ryan McConnehey"
Pool will create objects, pool will release and reclaim objects, and pool will delete objects.
If the pool manages the life time of the object then the pool can't release the object, correct. The pool will at most loan the object to the user.
You are looking for something that create objects and forbid about them, until you return that objects to the home. Is correct?
Did you mean forget instead of forbid. The kind of pool I'm talking about would only forget about those objects that it released. It still needs to manage the life time of the objects it didn't release.
Really, it's possible but it is not as a pool works, simply.
Are you stating that Boost.Pool doesn't work this way or all pools? Is there a definition for a pool that I'm missing. I thought a pool was a collection of objects and an object could be provided to the user. The implementation and life time of the object were left up to the pool.
Your idea breaks also raii pattern and you risk to have memory leaks, because not reclaimed objects maybe be lost during their life time.
In my requirements, to avoid memory leaks, the objects were passed to the user with a boost::shared_ptr.
What about a monostate pattern that globally manages objects as a pool and will be destroyed only when program terminates? That's can be a valid alternative, or not?
I believe the monostate pattern shares its (static) data. Wouldn't this mean the amount of data can't be increased? If the data can't be increased it not as useful to the user when all the objects have been used but more are still needed. Ryan _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
As far as I understand, you need to maintain a malloc'ed "your own" heap with some pool, but need to keep the heap alive if some objects are still in use but the pool is destroyed. boost::shared_ptr constructor that accepts deleter can be useful I guess. Sorry for abusing with bad formatted code: class PoolObjectDeleter { shared_ptr<void> pool_mem; weak_ptr<Pool> pool; PoolObjectDeleter(shared_ptr<Pool> & p, shared_ptr<void> & mem) : pool(p), pool_mem(mem) {} // provide copy constructor if customization needed void operator()(T* p) { // placement delete could go here shared_ptr<Pool> sp_pool = pool.lock(); if(sp_pool) sp_pool->deallocate(p); } } class Pool : enable_shared_from_this<Pool> { // ...implementation details... shared_ptr<void> pool_mem; shared_ptr<T> allocate() { T *obj; // ... find usable object... use palcement new if needed I guess PoolObjectDeleter d(shared_from_this(), this->pool_mem); shared_ptr<T> ret_value(obj, d); return ret_value; } void deallocate(T *p) { /* implementation */ } } Pool holds shared_ptr to memory, so if pool is destroyed and no objects are allocated / in use, memory released. It looks that one had to provide class to wrap malloc'ed memory malloc/free so that new/delete would work. When object is created, copy of deleter holds shared_ptr to memory protecting it from destruction, and weak_ptr to pool allowing user to destroy it. When pool is destroyed and some objects are still shared_pointed by user deleter could not deallocate it with pool, but still placement delete the object and reduce refcounter on memory, destroying it with last used object removal.
As far as I understand, you need to maintain a malloc'ed "your own" heap with some pool, but need to keep the heap alive if some objects are still in use but the pool is destroyed. boost::shared_ptr constructor that accepts deleter can be useful I guess. Sorry for abusing with bad formatted code:
class PoolObjectDeleter { shared_ptr<void> pool_mem; weak_ptr<Pool> pool; PoolObjectDeleter(shared_ptr<Pool> & p, shared_ptr<void> & mem) : pool(p), pool_mem(mem) {} // provide copy constructor if customization needed void operator()(T* p) { // placement delete could go here shared_ptr<Pool> sp_pool = pool.lock(); if(sp_pool) sp_pool->deallocate(p); } }
class Pool : enable_shared_from_this<Pool> { // ...implementation details... shared_ptr<void> pool_mem; shared_ptr<T> allocate() { T *obj; // ... find usable object... use palcement new if needed I guess PoolObjectDeleter d(shared_from_this(), this->pool_mem); shared_ptr<T> ret_value(obj, d); return ret_value; } void deallocate(T *p) { /* implementation */ } }
Pool holds shared_ptr to memory, so if pool is destroyed and no objects are allocated / in use, memory released. It looks that one had to provide class to wrap malloc'ed memory malloc/free so that new/delete would work. When object is created, copy of deleter holds shared_ptr to memory protecting it from destruction, and weak_ptr to pool allowing user to destroy it. When pool is destroyed and some objects are still shared_pointed by user deleter could not deallocate it with pool, but still placement delete the object and reduce refcounter on memory, destroying it with last used object removal. 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
Igore Dmit. wrote: 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. I have two questions. One, shouldn't the PoolObjectDeleter should be a template class? 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(). Ryan
2010/2/18 Ryan McConnehey
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_ptrasio::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
Hi, of course, in my opinion pool has to manage objects life time. However sharing objects with pool owner by shared ptr seems to be a good idea, because pool still manages objects life time. You are correct, the objects given to the user are still controlled by
michele.caini@gmail.com wrote: the pool but by passing the shared_ptr to the user the pool only has to worry about those item in its direct control. The downside to passing raw pointers to the user is the pool then has to keep track of which objects it has passed to the user and which objects are still available. This is an extra level detail that the shared_ptr allows us to avoid.
Using shared pointer also inside pool solves the problem, maybe. It is correct? I wasn't able to use the shared_ptr inside the pool. When creating the shared_ptr, the destructor function expects to call a function using the raw pointer. So the pool stores raw pointers but passes them to the user in a shared_ptr.
Ryan
participants (4)
-
Igore Dmit.
-
Lagrange
-
michele.caini@gmail.com
-
Ryan McConnehey