Venkat Peri
Venkat Peri

Reputation: 1754

Is this a correct method to store state for a std::allocator - in this case, backed by shared memory on Windows?

The implementation of a std::allocator (based on MAllocator) backed by Windows named shared memory, adds a couple of items to MAllocator.

Full code on github

Upvotes: 0

Views: 299

Answers (1)

Jonathan Wakely
Jonathan Wakely

Reputation: 171243

Firstly, your question says "for a std::allocator" but this is not a std::allocator, it's a ShmAllocator. std::allocator is a class template provided by the standard library, your allocator is not that class template, it's a different type. I think you mean "for an allocator" or just "for a standard allocator", which refers to a type conforming to the allocator requirements (std::allocator is just one example of such a type.)

This fails to meet the allocator requirements, specifically a copy is not equal to the original object. If you plan to use this allocator with code that expects a standard-conforming allocator it could fail. If you don't plan to use it with code that expects a standard allocator, then why bother copying its interface?

The requirements for the copy constructor require that for an object a of type ShmAllocator<T> the statement ShmAllocator<T> a1(a); is valid, with the post-condition that a1 == a, and for an object b of type ShmAllocator<U> the statement ShmAllocator<T> a(b); is valid, with the post-condition that ShmAllocator<U>(a) == b and a == ShmAllocator<T>(b).

These requirements are necessary because containers need to be able to rebind allocators and make copies which must be able to free each others memory. Equality for stateful allocators should be dependent on value not identity.

To make your allocator meet the requirements you could store mHandles as shared_ptr<mHandles> so that copies of the allocator can all share the same collection.

How do you plan to use this allocator? I don't know the Windows API functions, but it appears that every time you call allocate you need to use a different value for name or you will get the same pointer returned, which means it can't be used by standard containers. I would expect a shared-memory allocator to create a shared-memory region in its constructor (or be constructed with a reference to some existing region, e.g. see Boost.Interprocess allocators) then divide that region up and return different chunks of it every time allocate is called, rather than create a new region on every call to allocate. Is this intended to be user to share objects between processes? How will another process get access to an existing object? It seems the other process would have to call allocate to get a pointer to an already constructed object. That's confusing, allocate should give new, uninitialized memory. A shared-memory allocator would usually define a custom pointer type which stores an offset into the shared-memory region not an absolute address, so that when such a pointer is used in a different process the offset is still valid, even if the region is mapped to a different address.

Upvotes: 1

Related Questions