BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bdlma_blocklist

Detailed Description

Outline

Purpose

Provide allocation and management of a sequence of memory blocks.

Classes

See also
bdlma_infrequentdeleteblocklist

Description

This component implements a low-level memory manager, bdlma::BlockList, that allocates and manages a sequence of memory blocks, each of a potentially different size as specified during the allocate method's invocation. The release method of a bdlma::BlockList object deallocates the entire sequence of outstanding memory blocks, as does its destructor. Note that a bdlma::BlockList, at a minor memory expense, allows for individual items to be deallocated.

Usage

This section illustrates intended use of this component.

Example 1: Using a bdlma::BlockList in a Memory Pool

A bdlma::BlockList object is commonly used to supply memory to more elaborate memory managers that distribute parts of each (larger) allocated memory block supplied by the bdlma::BlockList object. The my_StrPool memory pool manager shown below requests relatively large blocks of memory from its bdlma::BlockList member object and distributes, via its allocate method, memory chunks of varying sizes from each block.

First, we define the interface of our my_StrPool class:

// my_strpool.h
class my_StrPool {
// DATA
bsls::Types::size_type d_blockSize; // size of current memory block
char *d_block_p; // current free memory block
bsls::Types::IntPtr d_cursor; // offset to next available byte
// in block
bdlma::BlockList d_blockList; // supplies managed memory blocks
private:
// PRIVATE MANIPULATORS
void *allocateBlock(bsls::Types::size_type numBytes);
// Request a new memory block of at least the specified 'numBytes'
// size and allocate the initial 'numBytes' from this block.
// Return the address of the allocated memory. The behavior is
// undefined unless '0 < numBytes'.
private:
// NOT IMPLEMENTED
my_StrPool(const my_StrPool&);
my_StrPool& operator=(const my_StrPool&);
public:
// CREATORS
my_StrPool(bslma::Allocator *basicAllocator = 0);
// Create a memory manager. Optionally specify a 'basicAllocator'
// used to supply memory. If 'basicAllocator' is 0, the currently
// installed default allocator is used.
~my_StrPool();
// Destroy this object and release all associated memory.
// MANIPULATORS
void *allocate(bsls::Types::size_type numBytes);
// Allocate the specified 'numBytes' of memory and return its
// address. If 'numBytes' is 0, return 0 with no other effect.
void release();
// Release all memory currently allocated through this object.
};
// MANIPULATORS
inline
void my_StrPool::release()
{
d_blockList.release();
d_block_p = 0;
}
Definition bdlma_blocklist.h:235
Definition bslma_allocator.h:457
std::size_t size_type
Definition bsls_types.h:124
std::ptrdiff_t IntPtr
Definition bsls_types.h:130

Finally, we provide the implementation of our my_StrPool class:

// my_strpool.cpp
enum {
k_INITIAL_SIZE = 128, // initial block size
k_GROWTH_FACTOR = 2, // multiplicative factor by which to grow block
k_THRESHOLD = 128 // size beyond which an individual block may be
// allocated if it doesn't fit in current block
};
// PRIVATE MANIPULATORS
void *my_StrPool::allocateBlock(bsls::Types::size_type numBytes)
{
assert(0 < numBytes);
if (k_THRESHOLD < numBytes) {
// Alloc separate block if above threshold.
return (char *)d_blockList.allocate(numBytes); // RETURN
}
else {
if (d_block_p) {
// Do not increase block size if no current block.
d_blockSize *= k_GROWTH_FACTOR;
}
d_block_p = (char *)d_blockList.allocate(d_blockSize);
d_cursor = numBytes;
return d_block_p; // RETURN
}
}
// CREATORS
my_StrPool::my_StrPool(bslma::Allocator *basicAllocator)
: d_blockSize(k_INITIAL_SIZE)
, d_block_p(0)
, d_blockList(basicAllocator) // the blocklist knows about 'bslma_default'
{
}
my_StrPool::~my_StrPool()
{
assert(k_INITIAL_SIZE <= d_blockSize);
assert(!d_block_p || (0 <= d_cursor &&
static_cast<bsls::Types::Uint64>(d_cursor) <= d_blockSize));
}
// MANIPULATORS
void *my_StrPool::allocate(bsls::Types::size_type numBytes)
{
if (0 == numBytes) {
return 0; // RETURN
}
if (d_block_p && numBytes + d_cursor <= d_blockSize) {
char *p = d_block_p + d_cursor;
d_cursor += numBytes;
return p; // RETURN
}
else {
return allocateBlock(numBytes); // RETURN
}
}
unsigned long long Uint64
Definition bsls_types.h:137

In the code shown above, the my_StrPool memory manager allocates from its bdlma::BlockList member object an initial memory block of size k_INITIAL_SIZE. This size is multiplied by k_GROWTH_FACTOR each time a depleted memory block is replaced by a newly-allocated block. The allocate method distributes memory from the current memory block piecemeal, except when the requested size either (1) is not available in the current block, or (2) exceeds the k_THRESHOLD_SIZE, in which case a separate memory block is allocated and returned. When the my_StrPool memory manager is destroyed, its bdlma::BlockList member object is also destroyed, which, in turn, automatically deallocates all of its managed memory blocks.