views:

202

answers:

2

This is an embarrassing question, but even the well-written documentation provided with boost.interprocess hasn't been enough for me to figure out how to do this.

What I have is a cached_adaptive_pool allocator instance, and I want to use it to construct an object, passing along constructor parameters:

struct Test {
  Test(float argument, bool flag);
  Test();
};

// Normal construction
Test obj(10, true);
// Normal dynamic allocation
Test* obj2 = new Test(20, false);

typedef managed_unique_ptr<
    Test, boost::interprocess::managed_shared_memory>::type unique_ptr;

// Dynamic allocation where allocator_instance == cached_adaptive_pool,
// using the default constructor
unique_ptr obj3 = allocator_instance.allocate_one()
// As above, but with the non-default constructor
unique_ptr obj4 = allocator_instance ... ???

This may very well be a failure on my part on how to use allocator objects in general. But in any case, I cannot see how to use this specific allocator, with the interface specified in cached_adaptive_pool to pass constructor arguments to my object.

cached_adaptive_pool has the method: void construct(const pointer & ptr, const_reference v) but I don't understand what that means and I can't find examples using it.

My head has been swimming in templates all day, so a helping hand, even if the answer is obvious, will be greatly appreciated.

+1  A: 

I guess I can always use placement new syntax. The idea is to dereference the smart pointer (in this case offset_ptr) returned by the allocator, and then pass the raw address to new().

unique_ptr obj = new(&(*allocator_instance.allocate_one())) Test(1,true)

Is this the idiomatic way of doing this? There are so many other places in boost where explicit support is provided to avoid using placement new, which makes me think not. In any case, I'll accept this answer if nothing better is provided in the near future.

UncleBens
When I tested it, new would only accept a raw pointer, not an offset_ptr which these allocator returns.
+1  A: 

cached_adaptive_pool has the method: void construct(const pointer & ptr, const_reference v) but I don't understand what that means and I can't find examples using it.

It should follow the interface of std::allocator, in which case allocate() gives you a suitable chunk of uninitialized memory and construct() calls placement new on the given pointer.

Something like:

allocator_instance.construct(allocator_instance.allocate_one(), Test(30, true));

Haven't used those pools myself, though. In C++0x, allocators should be able to call any constructor, not just the copy constructor, so it might be that boost's allocators already support this to an extent.

a.construct(p, 30, true); //a C++0x allocator would allow this and call new (p) Test(30, true)
UncleBens
Thanks. The first form is the kind of answer I expected, but was too confused and tired to realize myself. The second form `a.construct(p, 30, true)` doesn't seem to be supported by this specific boost allocator. Annoyingly enough, since `cached_adaptive_pool.construct()` returns `void`, I have to write `allocator_t::pointer obj = allocator.allocate_one(); allocator.construct(obj, Test(30, true))`? I'm not sure what's worse, using two statements for one simple operation or using a somewhat odd looking placement new directly.
You could make that a separate function.
UncleBens