Provide allocation and management of infrequently deleted blocks.
More...
Namespaces |
namespace | bdlma |
Detailed Description
- Outline
-
-
- Purpose:
- Provide allocation and management of infrequently deleted blocks.
-
- Classes:
-
- See also:
- Component bdlma_blocklist
-
- Description:
- This component implements a low-level memory manager,
bdlma::InfrequentDeleteBlockList
, 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::InfrequentDeleteBlockList
object deallocates the entire sequence of outstanding memory blocks, as does its destructor. Note that, in contrast to bdlma::BlockList
, the bdlma::InfrequentDeleteBlockList
class does not support the deallocation of individual items. In particular, although bdlma::InfrequentDeleteBlockList
has a deallocate
method, that method has no effect.
-
- Usage:
- This section illustrates intended use of this component.
-
- Example 1: Creating a Memory Pools for Strings:
- A
bdlma::InfrequentDeleteBlockList
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::InfrequentDeleteBlockList
object. The my_StrPool
memory pool manager shown below requests relatively large blocks of memory from its bdlma::InfrequentDeleteBlockList
member object and distributes memory chunks of varying sizes from each block on demand:
class my_StrPool {
char *d_block_p;
bsls::Types::size_type d_blockSize;
bsls::Types::IntPtr d_cursor;
bdlma::InfrequentDeleteBlockList
d_blockList;
private:
void *allocateBlock(bsls::Types::size_type numBytes);
private:
my_StrPool(const my_StrPool&);
my_StrPool& operator=(const my_StrPool&);
public:
explicit
my_StrPool(bslma::Allocator *basicAllocator = 0);
~my_StrPool();
void *allocate(bsls::Types::size_type size);
void release();
};
inline
void my_StrPool::release()
{
d_blockList.release();
d_block_p = 0;
}
enum {
k_INITIAL_SIZE = 128,
k_GROWTH_FACTOR = 2,
k_THRESHOLD = 128
};
void *my_StrPool::allocateBlock(bsls::Types::size_type numBytes)
{
assert(0 < numBytes);
if (k_THRESHOLD < numBytes) {
return reinterpret_cast<char *>(
d_blockList.allocate(numBytes));
}
if (d_block_p) {
d_blockSize *= k_GROWTH_FACTOR;
}
d_block_p = reinterpret_cast<char*>(d_blockList.allocate(d_blockSize));
d_cursor = numBytes;
return d_block_p;
}
my_StrPool::my_StrPool(bslma::Allocator *basicAllocator)
: d_block_p(0)
, d_blockSize(k_INITIAL_SIZE)
, d_cursor(0)
, d_blockList(basicAllocator)
{
}
my_StrPool::~my_StrPool()
{
assert(k_INITIAL_SIZE <= d_blockSize);
assert(!d_block_p || (0 <= d_cursor && d_cursor <=
static_cast<bsls::Types::IntPtr>(d_blockSize)));
}
void *my_StrPool::allocate(bsls::Types::size_type size)
{
if (0 == size) {
return 0;
}
if (d_block_p && size + d_cursor <= d_blockSize) {
char *p = d_block_p + d_cursor;
d_cursor += size;
return p;
}
else {
return allocateBlock(size);
}
}
In the code shown above, the my_StrPool
memory manager allocates from its bdlma::InfrequentDeleteBlockList
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 (1) is not available in the current block, or (2) exceeds the k_THRESHOLD
, in which case a separate memory block is allocated and returned. When the my_StrPool
memory manager is destroyed, its bdlma::InfrequentDeleteBlockList
member object is also destroyed, which in turn automatically deallocates all of its managed memory blocks.