Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ allocators, specifically passing constructor arguments to objects allocated with boost::interprocess::cached_adaptive_pool

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.

like image 496
porgarmingduod Avatar asked Apr 07 '10 21:04

porgarmingduod


2 Answers

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)
like image 94
UncleBens Avatar answered Nov 07 '22 16:11

UncleBens


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.

like image 1
porgarmingduod Avatar answered Nov 07 '22 15:11

porgarmingduod