Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is an Object Pool pattern of shared_ptr possible?

Is it possible to create an Object Pool of shared_ptr? Sketching this in my head, I can see two ways of doing this but each have a flaw:

  1. If T objects were stored in a reusable pool, the act of wrapping T in a shared_ptr on a get() request would result in the control block being re-allocated on the heap each time - therefore breaking the concept of an Object Pool.

  2. If shared_ptr objects were stored in a reusable pool, the shared_ptr object must stop existing to initiate a custom deleter, and the custom deleter function only gets called with a T pointer. So there is nothing to recycle.

like image 999
Nicholas Avatar asked Oct 14 '25 09:10

Nicholas


2 Answers

After exhaustive research and testing I have concluded that there is no legitimate way (as of C++11 or below) to make an object pool of reusable shared_ptr<T>'s directly. Certainly one can make a pool of T objects quite easily that serves shared_ptr<T>'s, but that results in heap allocation with every serve for the control block.

It is possible however to make an object pool of shared_ptr<T>'s indirectly (and this is the only way I have found to do it). By indirectly, I mean one must implement a custom 'memory pool' style allocator to store for reuse the memory released when shared_ptr<T> control blocks are destroyed. This allocator is then used as the third parameter of the `shared_ptr' constructor:

template< class Y, class Deleter, class Alloc > 
   std::shared_ptr( Y* ptr, Deleter d, Alloc alloc );

The shared_ptr<T> will still be constructed/allocated and deleted/de-allocated with heap memory - there is no way to stop it - but by making the memory reusable through the custom allocator, a deterministic memory footprint can be achieved.

like image 155
Nicholas Avatar answered Oct 16 '25 21:10

Nicholas


Yes, it's possible. But rather than making your pool return std::shared_ptr<T>, I would consider making it return boost::intrusive_ptr<T>. You could have intrusive_ptr_release() be responsible for freeing that block from the pool, and then it's just up to your users to construct T such that you can make an intrusive_ptr<T>.

like image 25
Barry Avatar answered Oct 16 '25 22:10

Barry