Quick Links: |
Provide efficient allocation of memory blocks of uniform size. More...
Namespaces | |
namespace | bdlma |
Functions | |
void * | operator new (bsl::size_t size, BloombergLP::bdlma::Pool &pool) |
void | operator delete (void *address, BloombergLP::bdlma::Pool &pool) |
bdlma::Pool | memory manager that allocates memory blocks of uniform size |
bdlma::Pool
, that allocates and manages maximally-aligned memory blocks of some uniform size specified at construction. A bdlma::Pool
object maintains an internal linked list of free memory blocks, and dispenses one block for each allocate
method invocation. When a memory block is deallocated, it is returned to the free list for potential reuse. bdlma::Pool
replenishes the list by first allocating a large, contiguous "chunk" of memory, then splitting the chunk into multiple memory blocks. A chunk and its constituent memory blocks can be depicted visually: +-----+--- memory blocks of uniform size
| |
----- ----- ------------
| | | ... |
=====^=====^============
\___________ __________/
V
a "chunk"
bdlma::Pool
, clients must specify the specific block size managed and dispensed by the pool. Furthermore, clients can optionally configure: bslma_default
). 1, 2, 4, 8, 16, 30, 30, 30 ...
30, 30, 30 ...
bdlma::Pool
was created. operator new
to allow convenient syntax for the construction of objects using a bdlma::Pool
. The new
operator supplied in this component takes a bdlma::Pool
argument indicating the source of the memory. Consider the following use of standard placement new
syntax (supplied by bsl_new.h
) along with a bdlma::Pool
to allocate an object of type T
. Note that the size of T
must be the same or smaller than the blockSize
with which the pool is constructed: void f(bdlma::Pool *pool) { assert(pool->blockSize() >= sizeof(T)); T *t = new (pool->allocate()) T(...); // ... }
T
throws an exception, pool->deallocate
is never called. operator new
: ::operator new(bsl::size_t size, BloombergLP::bdlma::Pool& pool);
pool->deallocate
is called in the case of an exception: void f(bdlma::Pool *pool) { assert(pool->blockSize() >= sizeof(T)); T *t = new (*pool) T(...); // ...
delete
should not be called directly. Instead, this component provides a static template member function deleteObject
, parameterized on TYPE
: pool->deleteObject(t); }
deleteObject
call is equivalent to performing the following: t->~TYPE(); pool->deallocate(t);
delete
is supplied solely to allow the compiler to arrange for it to be called in case of an exception. bdlma::Pool
can be used by node-based containers (such as lists, trees, and hash tables that hold multiple elements of uniform size) for efficient memory allocation of new elements. The following container template class, my_PooledArray
, stores values of (template parameter) TYPE
"out-of-place" as nodes in a vector
of pointers. Since the size of each node is fixed and known a priori, the class uses a bdlma::Pool
to allocate memory for the nodes to improve memory allocation efficiency. Note that for simplicity, we assume that TYPE
does not require an allocator, and that calls to the destructor of TYPE
can be elided. my_PooledArray
template class: // my_poolarray.h template <class TYPE> class my_PooledArray { // This class implements a container that stores values of (template // parameter) 'TYPE' out-of-place. It is assumed that 'TYPE' does not // require an allocator, and that calls to the destructor of 'TYPE' can // be elided. // DATA bsl::vector<TYPE *> d_array_p; // array of pooled elements bdlma::Pool d_pool; // memory manager for array elements private: // Not implemented: my_PooledArray(const my_PooledArray&); public: // CREATORS explicit my_PooledArray(bslma::Allocator *basicAllocator = 0); // Create a pooled array that stores the 'TYPE' element values // "out-of-place". Optionally specify a 'basicAllocator' used to // supply memory. If 'basicAllocator' is 0, the currently // installed default allocator is used. ~my_PooledArray(); // Destroy this array and all elements held by it. // MANIPULATORS void append(const TYPE& value); // Append the specified 'value' to this array. void removeAll(); // Remove all elements from this array. // ACCESSORS bsl::size_t length() const; // Return the number of elements in this array. const TYPE& operator[](int index) const; // Return a reference providing non-modifiable access to the value // at the specified 'index' in this array. The behavior is // undefined unless '0 <= index < length()'. };
my_PooledArray
methods that are defined inline
. removeAll
method, all elements are deallocated by simply invoking the pool's release
method. This technique implies significant performance gain when the array contains many elements: // MANIPULATORS template <class TYPE> inline void my_PooledArray<TYPE>::removeAll() { d_array_p.clear(); d_pool.release(); } // ACCESSORS template <class TYPE> inline bsl::size_t my_PooledArray<TYPE>::length() const { return d_array_p.size(); } template <class TYPE> inline const TYPE& my_PooledArray<TYPE>::operator[](int index) const { assert(0 <= index); assert(index < static_cast<int>(length())); return *d_array_p[index]; }
my_PooledArray
methods that are defined in the .cpp
file. bdlma::Pool
: // my_poolarray.cpp // CREATORS template <class TYPE> my_PooledArray<TYPE>::my_PooledArray(bslma::Allocator *basicAllocator) : d_array_p(basicAllocator) , d_pool(sizeof(TYPE), basicAllocator) { }
d_pool
, we do not have to explicitly invoke deleteObject
to reclaim outstanding memory. The destructor of the pool will automatically deallocate all array elements: template <class TYPE> my_PooledArray<TYPE>::~my_PooledArray() { // Elements are automatically deallocated when 'd_pool' is destroyed. }
new
is used to allocate new nodes in the append
method: // MANIPULATORS template <class TYPE> void my_PooledArray<TYPE>::append(const TYPE& value) { TYPE *tmp = new (d_pool) TYPE(value); d_array_p.push_back(tmp); }
void* operator new | ( | bsl::size_t | size, | |
BloombergLP::bdlma::Pool & | pool | |||
) |
Return a block of memory of the specified size
(in bytes) allocated from the specified pool
. The behavior is undefined unless size
is the same or smaller than the blockSize
with which pool
was constructed. Note that an object may allocate additional memory internally, requiring the allocator to be passed in as a constructor argument:
my_Type *newMyType(bdlma::Pool *pool, bslma::Allocator *basicAllocator) { return new (*pool) my_Type(..., basicAllocator); }
Also note that the analogous version of operator delete
should not be called directly. Instead, this component provides a static template member function, deleteObject
, parameterized by TYPE
:
void deleteMyType(my_Type *t, bdlma::Pool *pool) { pool->deleteObject(t); }
deleteObject
performs the following:
t->~my_Type(); pool->deallocate(t);
void operator delete | ( | void * | address, | |
BloombergLP::bdlma::Pool & | pool | |||
) |
Use the specified pool
to deallocate the memory at the specified address
. The behavior is undefined unless address
is non-zero, was allocated using pool
, and has not already been deallocated. Note that this operator is supplied solely to allow the compiler to arrange for it to be called in the case of an exception.