BDE 4.14.0 Production release
|
Provide a memory allocator that counts allocated bytes.
This component provides a special-purpose counting allocator, bdlma::CountingAllocator
, that implements the bslma::Allocator
protocol and provides instrumentation to track: (1) the number of bytes currently in use (numBytesInUse
), and (2) the cumulative number of bytes that have ever been allocated (numBytesTotal
). The accumulated statistics are based solely on the number of bytes requested in calls to the allocate
method. A print
method is provided to output the current state of the allocator's byte counts to a specified bsl::ostream
:
Like many other allocators, bdlma::CountingAllocator
relies on the currently installed default allocator (see bslma_default ) at construction. Clients may, however, override this allocator by supplying (at construction) any other allocator implementing the bslma::Allocator
protocol provided that it is fully thread-safe.
Note that a bdlma::CountingAllocator
necessarily incurs some overhead in order to provide its byte-counting functionality. However, this overhead is substantially less than that incurred by the bslma::TestAllocator
(see bslma_testallocator ), which keeps track of the same two statistics that are maintained by a bdlma::CountingAllocator
. Consequently, use of a bdlma::CountingAllocator
may be appropriate in cases where the overhead of bslma::TestAllocator
is too onerous. In particular, a counting allocator may be suitable even for production use in certain situations, whereas the test allocator is not intended for production use under any circumstance.
The two byte counts maintained by bdlma::CountingAllocator
are initialized to 0 at construction and increased with each call to allocate
by size
, i.e., by the actual number of bytes requested. Each call to deallocate
decreases the numBytesInUse
count by the same amount by which the byte count was increased in the original allocate
call. The number of bytes currently in use is returned by numBytesInUse
and the total number of bytes ever allocated is returned by numBytesTotal
.
The bdlma::CountingAllocator
class is fully thread-safe (see bsldoc_glossary ) provided that the underlying allocator (established at construction) is fully thread-safe.
This section illustrates intended use of this component.
In this example, we demonstrate how a counting allocator may be used to track the amount of dynamic memory used by a container. The container used for illustration is DoubleStack
, a stack of out-of-place double
values.
First, we show the interface of the DoubleStack
class:
Next, we show the (elided) implementation of DoubleStack
.
The default constructor creates a stack having the capacity for one element (the implementation of the destructor is not shown):
The push
method first ensures that the array has sufficient capacity to accommodate an additional value, then allocates a block in which to store that value:
The pop
method asserts that the stack is not empty before deallocating the block used to store the element at the top of the stack:
The push
method (above) made use of the private increaseCapacity
method, which, in turn, makes use of the reallocate
helper function (static
to the .cpp
file). Note that increaseCapacity
(below) increases the capacity of the double *
array by a factor of 2 each time that it is called:
Now, we are ready to employ a CountingAllocator
to illustrate the dynamic memory use of DoubleStack
. We first define two constants that facilitate portability of this example across 32- and 64-bit platforms:
First, we define a CountingAllocator
, ca
. At construction, a counting allocator can be configured with an optional name and an optional allocator. In this case, we give ca
a name to distinguish it from other counting allocators, but settle for using the default allocator:
Next, we create a DoubleStack
, supplying it with ca
, and assert the expected memory use incurred by the default constructor:
Next, we push an element onto the stack. The first push incurs an additional allocation to store (out-of-place) the value being inserted:
Next, we push a second element onto the stack. In this case, two allocations result, one due to the resizing of the internal array and one required to store the new value out-of-place:
Next, we pop the top-most element from the stack. The number of bytes in use decreases by the amount used to store the popped element out-of-place:
Finally, we print the state of ca
to standard output:
which displays the following on a 32-bit platform: