|
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: