From: Ion Gaztañaga (igaztanaga_at_[hidden])
Date: 2006-12-29 03:51:35


Mathias Gaunard wrote:
> The boost inteprocess documentation [1] says that all objects must be
> constructed-destroyed via allocator::construct and allocator::destroy
> functions when using the interprocess allocators.
>
> However, according to the draft of the next C++ Standard [2] 20.1.6/2,
> allocator::construct is strictly equivalent to placement new and
> allocator::destroy stricly equivalent to a call to the destructor, with
> the pointer type casted to void*.
>
> Therefore why is such a requirement necessary?

Basically because the pointer type of Interprocess allocators is not a
raw pointer, but a relative one (offset_ptr). This way containers using
allocator::pointer as their pointer type can be mapped by different
processes, in different base addresses. If you try to do this:

using boost::interprocess;

typedef allocator<MyClass, managed_shared_memory::segment_manager> MyAlloc;

managed_shared_memory mem();

MyAlloc alloc(mem.get_segment_manager());

MyClass *myclass = new(alloc.allocate(1)) MyClass;

you will get a compilation error, because "allocate" returns
allocator::pointer and that pointer is not MyClass * but
offset_ptr<MyClass>. You can get the raw pointer from offset_ptr<> using
offset_ptr<T>::get() method. That's why containers should use
allocator::construct() that is defined like:

    void construct(const pointer &ptr, const Convertible &value)
    { new(detail::get_pointer(ptr)) value_type(value); }

It's conforming for a STL container to ignore allocator::pointer and
suppose it's a raw pointer, but this sadly can support shared memory or
any other smart pointer based allocators.

Regards,

Ion