I want objects managed by a shared_ptr to be allocated from a pool, say Boost's Pool interface, how can this be achieved?
These are almost orthogonal concerns. shared_ptr
plays no part in allocation of objects.
Where it is concerned is in the deletion of memory no longer referenced. If you have allocated from anything other than the default heap you'll need to provide a custom deleter
Evident solution:
Create your own make_shared
function and enforce the use of this method to created shared_ptr
. Those who derive from The Rule shall be punished.
Note:
There seems to be a confusion with the role of the shared_ptr
. Its role is to manage memory than YOU have allocated, however to do so it requires some allocation of its own (counter and deleter), thus you may pass it an allocator for those.
Here's the code to do what you want (probably won't compile as I don't have boost on hand and I'm writing it from memory):
class YourClass; // your data type, defined somewhere else
boost::object_pool<YourClass> allocator;
void destroy(YourClass* pointer)
{
allocator.destroy(pointer);
}
boost::shared_ptr<YourClass> create()
{
// usage of object_pool<??>::construct requires that you have a
// YourClass::YourClass(void) defined. If you need to pass arguments
// to the new instance, you need to do that separately.
//
// for example using a YourClass::Initialize(your,parameters,here) method
// before returning from this function
return boost::shared_ptr<YourClass>( allocator.construct(), &destroy );
}
// usage:
boost::shared_ptr<YourClass> newObject = create();
I implemented this twice, in two different projects. In both, the create and destroy functions were synchronized (you can add a boost::mutex
lock around the use of allocator) and they were members of a factory class (and the destroy
's signature was modified to void (YourClass*)
through the usage of boost::bind
).
You can also avoid writing two extra functions (the destroy
and create
) by binding object_pool<YourClass>::destroy
dirrectly in the boost::shared_ptr constructor.
I'm too lazy to write all that now :).
Edit (moved my answer comment in here for the code formatting):
To bind the destroy function:
class ClassFactory
{
boost::object_pool<YourClass> allocator;
public:
boost::shared_ptr<YourClass> create()
{
return boost::shared_ptr<YourClass>(
allocator.construct(),
boost::bind(&ClassFactory::destroy, this, _1) );
}
void destroy(YourClass* p)
{
allocator.destroy(pointer);
}
};
ClassFactory
should have a longer lifetime than the shared_ptr
(if the ClassFactory
instance is deleted, the this pointer passed to the shared_ptr
instance will be invalid - and crash your app when the shared_ptr
deletes the YourClass
instance).