HiveBrain v1.2.0
Get Started
← Back to all entries
patterncppMinor

Boost::pool based STL vector allocator

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
booststlbasedpoolallocatorvector

Problem

I wrote an STL allocator which uses boost::pool to allocate the memory for std::vector container.

This is my first time I implement an allocator and while working on this class I found that STL containers (std::vector for example) copy, destruct, create many times the assigned allocator during their lifetime. For example, during pushing operation into std::vector, the allocator's copy constructor and destructor are called several times. Due to this I also had to wrap the boost::pool with a smart pointer because when I was passing the pool as external argument and then destroying it explicitly I was getting crashes on program exist inside the allocator because some clones of it were still trying to access the pool. I am still not sure I completely understand the mechanics of how STL containers treat allocators during their lifetime. Therefore I am asking to review this class implementation.

Also I would like to have the answer to the following questions:

-
Is this the right way to use boost::pool for raw memory allocation? My intention was to allocate a large pool (in this example it is just 4096 bytes) of single byte blocks to mimic raw heap memory arena, because the allocator interface requests the memory in varying sizes multiplied by the data size.

-
If the answer to the question above is positive, can I share the same allocator instance between several std::vector instances (with the same data type)? Besides thread unsafety, what are the possible caveats or pitfalls I need to take into account?

```
template
class Allocator{

friend class Allocator;
private:
typedef std::shared_ptr > PoolSP;
PoolSP m_pool;

public:

typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef T* pointer;
typedef const T* const_pointer;
typedef T& reference;
typedef const T& const_reference;
typedef T value_type;

/// Default constructor
Allocator() throw()
{
m_allocUsedSize = 0;
m_pool.reset(new boost::pool<>(sizeof(uint8_t), 4096));

}
/

Solution

Stateless C++11 allocators

Allocators were at first (my opinion) designed to be simple empty classes / templates, to just call malloc or similar function. They are treated this way as if copying was no-cost. I would personally design it in a bit different way, but I understand that it is what it is.

Allocator must therefore be either empty (with only static/shared members) or a reference/pointer to the real logic. Using shared_pointer is therefore fine and satisfy the stateless requirement as I understand it (it handles the destruction as well).

boost::pool as allocator

This is actually something I have used myself for tiny blocks. It can help a lot if your application needs to allocate many tiny objects (2-3 pointers/integers per object). But beware...

used in std::vector

But vector is not so good with such an allocator, tree would be. The problem is that vector is an array, which reallocates as needed. That often means that new array is created, items copyed and old array destroyed. Container that does not reallocate its node would be better (e.g. tree or deque). In better words: boost::pool would better be utilized with such "no-destroy unless deleting" container.

using single allocator in multiple containers

Yes, of course you can. But take care about thread-safety and copy/move constructors (which you solved by using shared_pointer).

the code

Well, your indentation may need some improvements, your last line looks like you have the counter outside of the class. But other than that, I can see no errors.

Context

StackExchange Code Review Q#101192, answer score: 4

Revisions (0)

No revisions yet.