views:

388

answers:

3

I want objects managed by a shared_ptr to be allocated from a pool, say Boost's Pool interface, how can this be achieved?

+1  A: 

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

Phil Nash
As I understand it, shared_ptr can be defined to take a custom allocator:`template<class Y, class D, class A> shared_ptr(Y * p, D d, A a);`The question is, what goes for D if I were to use Boost's pool_alloc
myahya
The allocator is for the counter object
Phil Nash
+1  A: 

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.

Matthieu M.
Couldn't you use `boost::allocate_shared` with `boost::pool_alloc`?
dvide
+3  A: 

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).

utnapistim
Thanks, this is what I was looking for. I would be interested in seeing how it is done using a factory class, I am having issues in binding the destroy function.
myahya