// ball_countingallocator.h -*-C++-*- // ---------------------------------------------------------------------------- // NOTICE // // This component is not up to date with current BDE coding standards, and // should not be used as an example for new development. // ---------------------------------------------------------------------------- #ifndef INCLUDED_BALL_COUNTINGALLOCATOR #define INCLUDED_BALL_COUNTINGALLOCATOR #include <bsls_ident.h> BSLS_IDENT("$Id: $") //@PURPOSE: Provide a concrete allocator that keeps count of allocated bytes. // //@CLASSES: // ball::CountingAllocator: maximally-aligning, instrumented allocator adaptor // //@SEE_ALSO: ball_fixedsizerecordbuffer // //@DESCRIPTION: This component provides a special-purpose instrumented // allocator, 'ball::CountingAllocator', that implements the 'bslma::Allocator' // protocol and guarantees maximal alignment of allocated blocks, even when // the allocator supplied at construction guarantees only natural alignment // (or no alignment at all). 'ball::CountingAllocator' maintains a // user-resettable running sum of the total number of bytes // allocated (called byte count, see below). //.. // ,-----------------------. // ( ball::CountingAllocator ) // `-----------------------' // | ctor/dtor // | numBytesTotal // | resetNumBytesTotal // V // ,----------------. // ( bslma::Allocator ) // `----------------' // allocate // deallocate //.. // ///Byte Count ///---------- // The byte count maintained by 'ball::CountingAllocator' is set to 0 upon // construction and after each call to 'resetNumBytesTotal'. Each call of // 'allocate(size)' increases the byte count by the sum of the least // multiple of 'bsls::AlignmentUtil::BSLS_MAX_ALIGNMENT' that is greater than // or equal to 'size' and 'bsls::AlignmentUtil::BSLS_MAX_ALIGNMENT'. Each call // of 'deallocate' decrements the byte count by the same amount by which the // byte count was incremented on matching 'allocate' call. The current // value of the byte count is returned by the 'numBytesTotal' accessor. // ///Usage ///----- // In the following example we demonstrate how the counting allocator can // be used to know the amount of dynamic memory allocated by a // 'vector<int>' after pushing one integer. Let us assume that memory for // the vector comes from a 'bslma::Allocator' named 'allocator'. //.. // // First create the counting allocator using 'allocator'. // BloombergLP::ball::CountingAllocator countingAllocator(allocator); // // // Now create the vector using the counting allocator. // bsl::vector<int> vec(&countingAllocator); // // vec.push_back(1); // // The following will print the memory consumed by the // // vector and the counting allocator. // bsl::cout << "dynamic memory after first push back: " // << countingAllocator.numBytesTotal() << bsl::endl; //.. #include <balscm_version.h> #include <bslma_allocator.h> #include <bslma_default.h> #include <bsls_alignmentutil.h> namespace BloombergLP { namespace ball { // ======================= // class CountingAllocator // ======================= class CountingAllocator : public bslma::Allocator { // This class maintains a count of the total number of allocated bytes. // The running byte count is initialized to 0 upon construction, is // increased by the 'allocate' method, and may be reset to 0 by the // 'resetNumBytesTotal' method. The 'deallocate' method appropriately // decrement the byte count. The precise definition of byte count is // described in the "Byte Count" section of the component-level // documentation. // DATA size_type d_byteCount; // byte count bslma::Allocator *d_allocator_p; // holds (but does not own) allocator private: // NOT IMPLEMENTED CountingAllocator(const CountingAllocator&); CountingAllocator& operator=(const CountingAllocator&); public: // CREATORS explicit CountingAllocator(bslma::Allocator *basicAllocator = 0); // Create a counting allocator having an initial byte count of 0. // Optionally specify a 'basicAllocator' used to supply memory. If // 'basicAllocator' is 0, the currently installed default allocator is // used. virtual ~CountingAllocator(); // Destroy this counting allocator. // MANIPULATORS virtual void *allocate(size_type size); // Return a newly allocated block of memory of (at least) the specified // positive 'size' (bytes) and increment the byte count maintained by // this counting allocator by the sum of the least multiple of // 'bsls::AlignmentUtil::BSLS_MAX_ALIGNMENT' that is greater than or // equal to 'size' and 'bsls::AlignmentUtil::BSLS_MAX_ALIGNMENT'. The // behavior is undefined unless '0 <= size'. Note that the alignment // of the address returned is the maximum alignment for any fundamental // type defined for the calling platform, even if the supplied // allocator guarantees only natural alignment. virtual void deallocate(void *address); // Return the memory at the specified 'address' back to this allocator // and update the byte count maintained by this counting allocator // appropriately. If 'address' is 0, this function has no effect. The // behavior is undefined unless 'address' was allocated using this // allocator and has not already been deallocated. void resetNumBytesTotal(); // Reset the byte count maintained by this counting allocator to 0. // ACCESSORS size_type numBytesTotal() const; // Return the byte count maintained by this counting allocator. The // precise definition of byte count is described in the "Byte Count" // section of the component-level documentation. }; // ============================================================================ // INLINE DEFINITIONS // ============================================================================ // ----------------------- // class CountingAllocator // ----------------------- // CREATORS inline CountingAllocator::CountingAllocator(bslma::Allocator *basicAllocator) : d_byteCount(0) , d_allocator_p(bslma::Default::allocator(basicAllocator)) { } // MANIPULATORS inline void *CountingAllocator::allocate(size_type size) { size_type paddedSize = bsls::AlignmentUtil::roundUpToMaximalAlignment(size); size_type totalSize = paddedSize + bsls::AlignmentUtil::BSLS_MAX_ALIGNMENT; d_byteCount += totalSize; void *address = d_allocator_p->allocate(totalSize); *((int *)address) = static_cast<int>(totalSize); return (char *)address + bsls::AlignmentUtil::BSLS_MAX_ALIGNMENT; } inline void CountingAllocator::deallocate(void *address) { if (address) { address = (char *)address - bsls::AlignmentUtil::BSLS_MAX_ALIGNMENT; d_byteCount -= *((int *)address); d_allocator_p->deallocate(address); } } inline void CountingAllocator::resetNumBytesTotal() { d_byteCount = 0; } // ACCESSORS inline CountingAllocator::size_type CountingAllocator::numBytesTotal() const { return d_byteCount; } } // close package namespace } // close enterprise namespace #endif // ---------------------------------------------------------------------------- // Copyright 2015 Bloomberg Finance L.P. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // ----------------------------- END-OF-FILE ----------------------------------