// bdlma_sequentialpool.h -*-C++-*- #ifndef INCLUDED_BDLMA_SEQUENTIALPOOL #define INCLUDED_BDLMA_SEQUENTIALPOOL #include <bsls_ident.h> BSLS_IDENT("$Id: $") //@PURPOSE: Provide sequential memory using dynamically-allocated buffers. // //@CLASSES: // bdlma::SequentialPool: memory pool using dynamically-allocated buffers // //@SEE_ALSO: bdlma_infrequentdeleteblocklist, bdlma_sequentialallocator // //@DESCRIPTION: This component provides a fast sequential memory pool, // 'bdlma::SequentialPool', that dispenses heterogeneous memory blocks (of // varying, user-specified sizes) from a dynamically-allocated internal buffer. // If an allocation request exceeds the remaining free memory space in the // internal buffer, the pool either replenishes its buffer with new memory to // satisfy the request, or returns a separate memory block, depending on // whether the request size exceeds an optionally-specified maximum buffer // size. The 'release' method releases all memory allocated through the pool, // as does the destructor. The 'rewind' method releases all memory allocated // through the pool and returns to the underlying allocator *only* memory that // was allocated outside of the typical internal buffer growth of the pool // (i.e., large blocks). Note that individually allocated memory blocks cannot // be separately deallocated. // // A 'bdlma::SequentialPool' is typically used when fast allocation and // deallocation is needed, but the user does not know in advance the maximum // amount of memory needed. // ///Optional 'initialSize' Parameter ///-------------------------------- // An optional 'initialSize' parameter can be supplied at construction to // specify the initial size of the internal buffer. If 'initialSize' is not // supplied, an implementation-defined value is used for the initial internal // size of the buffer. // ///Optional 'maxBufferSize' Parameter /// - - - - - - - - - - - - - - - - - // If 'initialSize' is specified, an optional 'maxBufferSize' parameter can be // supplied at construction to specify the maximum buffer size for geometric // growth. Once the internal buffer grows up to the 'maxBufferSize', further // requests that exceed this size will be served by a separate memory block // instead of the internal buffer. The behavior is undefined unless // 'maxBufferSize >= initialSize'. Note that 'reserveCapacity' always ensures // that the requested number of bytes is available (allocating a new internal // buffer if necessary) regardless of whether the size of the request exceeds // 'maxBufferSize'. // ///Optional 'growthStrategy' Parameter ///----------------------------------- // An optional 'growthStrategy' parameter can be supplied at construction to // specify the growth rate of the dynamically-allocated buffers. The buffers // can grow either geometrically or remain constant in size. If // 'growthStrategy' is not specified, geometric growth is used. See // 'bsls_blockgrowth' for more details. // ///Optional 'alignmentStrategy' Parameter ///-------------------------------------- // An optional 'alignmentStrategy' parameter can be supplied at construction to // specify the memory alignment strategy. Allocated memory blocks can either // follow maximum alignment, natural alignment, or 1-byte alignment. If // 'alignmentStrategy' is not specified, natural alignment is used. See // 'bsls_alignment' for more details. // ///Usage ///----- // This section illustrates intended use of this component. // ///Example 1: Using 'bdlma::SequentialPool' for Efficient Allocations /// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Suppose we define a container class, 'my_IntDoubleArray', that holds both // 'int' and 'double' values. The class can be implemented using two parallel // arrays: one storing the type information, and the other storing pointers to // the 'int' and 'double' values. For efficient memory allocation, we can use // a 'bdlma::SequentialPool' for memory allocation: //.. // // my_intdoublearray.h // // class my_IntDoubleArray { // // This class implements an efficient container for an array that // // stores both 'int' and 'double' values. // // // DATA // char *d_typeArray_p; // array indicating the type of corresponding // // values stored in 'd_valueArray_p' // // void **d_valueArray_p; // array of pointers to the values stored // // int d_length; // number of values stored // // int d_capacity; // physical capacity of the type and value // // arrays // // bdlma::SequentialPool // d_pool; // sequential memory pool used to supply memory // // private: // // PRIVATE MANIPULATORS // void increaseSize(); // // Increase the capacity of the internal arrays used to store // // elements added to this array by at least one element. // // // Not implemented: // my_IntDoubleArray(const my_IntDoubleArray&); // // public: // // TYPES // enum Type { k_MY_INT, k_MY_DOUBLE }; // // // CREATORS // explicit my_IntDoubleArray(bslma::Allocator *basicAllocator = 0); // // Create an 'int'-'double' array. Optionally specify a // // 'basicAllocator' used to supply memory. If 'basicAllocator' is // // 0, the currently installed default allocator is used. // // ~my_IntDoubleArray(); // // Destroy this array and all elements held by it. // // // ... // // // MANIPULATORS // void appendInt(int value); // // Append the specified 'int' 'value' to this array. // // void appendDouble(double value); // // Append the specified 'double' 'value' to this array. // // void removeAll(); // // Remove all elements from this array. // // // ... // }; //.. // The use of a sequential pool and the 'release' method allows the 'removeAll' // method to quickly deallocate memory of all elements: //.. // // MANIPULATORS // inline // void my_IntDoubleArray::removeAll() // { // d_pool.release(); // d_length = 0; // } //.. // The sequential pool optimizes the allocation of memory by using // dynamically-allocated buffers to supply memory. This greatly reduces the // amount of dynamic allocation needed: //.. // // my_intdoublearray.cpp // // enum { k_INITIAL_SIZE = 1 }; // // // PRIVATE MANIPULATORS // void my_IntDoubleArray::increaseSize() // { // // Implementation elided. // // ... // } // // // CREATORS // my_IntDoubleArray::my_IntDoubleArray(bslma::Allocator *basicAllocator) // : d_length(0) // , d_capacity(k_INITIAL_SIZE) // , d_pool(basicAllocator) // { // d_typeArray_p = static_cast<char *>( // d_pool.allocate(d_capacity * sizeof *d_typeArray_p)); // d_valueArray_p = static_cast<void **>( // d_pool.allocate(d_capacity * sizeof *d_valueArray_p)); // } //.. // Note that in the destructor, all outstanding memory blocks are deallocated // automatically when 'd_pool' is destroyed: //.. // my_IntDoubleArray::~my_IntDoubleArray() // { // assert(0 <= d_length); // assert(0 <= d_capacity); // assert(d_length <= d_capacity); // } // // // MANIPULATORS // void my_IntDoubleArray::appendInt(int value) // { // if (d_length >= d_capacity) { // increaseSize(); // } // // int *item = static_cast<int *>(d_pool.allocate(sizeof *item)); // *item = value; // // d_typeArray_p[d_length] = static_cast<char>(k_MY_INT); // d_valueArray_p[d_length] = item; // // ++d_length; // } // // void my_IntDoubleArray::appendDouble(double value) // { // if (d_length >= d_capacity) { // increaseSize(); // } // // double *item = static_cast<double *>(d_pool.allocate(sizeof *item)); // *item = value; // // d_typeArray_p[d_length] = static_cast<char>(k_MY_DOUBLE); // d_valueArray_p[d_length] = item; // // ++d_length; // } //.. // ///Example 2: Implementing an Allocator Using 'bdlma::SequentialPool' /// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // 'bslma::Allocator' is used throughout the interfaces of BDE components. // Suppose we would like to create a fast allocator, 'my_FastAllocator', that // allocates memory from a buffer in a similar fashion to // 'bdlma::SequentialPool'. 'bdlma::SequentialPool' can be used directly to // implement such an allocator. // // Note that the documentation for this class is simplified for this usage // example. Please see 'bdlma_sequentialallocator' for full documentation of a // similar class. //.. // class my_SequentialAllocator : public bslma::Allocator { // // This class implements the 'bslma::Allocator' protocol to provide a // // fast allocator of heterogeneous blocks of memory (of varying, // // user-specified sizes) from dynamically-allocated internal buffers. // // // DATA // bdlma::SequentialPool d_pool; // memory manager for allocated memory // // blocks // // public: // // CREATORS // explicit my_SequentialAllocator(bslma::Allocator *basicAllocator = 0); // // Create an allocator for allocating memory blocks from // // dynamically-allocated internal buffers. Optionally specify a // // 'basicAllocator' used to supply memory. If 'basicAllocator' is // // 0, the currently installed default allocator is used. // // ~my_SequentialAllocator(); // // Destroy this allocator. All memory allocated from this // // allocator is released. // // // MANIPULATORS // virtual void *allocate(size_type size); // // Return the address of a contiguous block of memory of the // // specified 'size' (in bytes). // // virtual void deallocate(void *address); // // This method has no effect on the memory block at the specified // // 'address' as all memory allocated by this allocator is managed. // // The behavior is undefined unless 'address' was allocated by this // // allocator, and has not already been deallocated. // }; // // // CREATORS // inline // my_SequentialAllocator::my_SequentialAllocator( // bslma::Allocator *basicAllocator) // : d_pool(basicAllocator) // { // } // // inline // my_SequentialAllocator::~my_SequentialAllocator() // { // d_pool.release(); // } // // // MANIPULATORS // inline // void *my_SequentialAllocator::allocate(size_type size) // { // return d_pool.allocate(size); // } // // inline // void my_SequentialAllocator::deallocate(void *) // { // } //.. #include <bdlscm_version.h> #include <bdlma_buffermanager.h> #include <bdlma_infrequentdeleteblocklist.h> #include <bslma_allocator.h> #include <bsls_alignment.h> #include <bsls_alignmentutil.h> #include <bsls_assert.h> #include <bsls_blockgrowth.h> #include <bsls_objectbuffer.h> #include <bsls_performancehint.h> #include <bsls_platform.h> #include <bsls_review.h> #include <bsls_types.h> #include <bsl_cstddef.h> #include <bsl_cstdint.h> namespace BloombergLP { namespace bdlma { // ==================== // class SequentialPool // ==================== class SequentialPool { // This class implements a fast memory pool that efficiently dispenses // heterogeneous blocks of memory (of varying, user-specified sizes) from a // sequence of dynamically-allocated internal buffers. Memory for the // internal buffers is supplied by an (optional) allocator supplied at // construction; if no allocator is supplied, the currently installed // default allocator is used. If an allocation exceeds the remaining free // memory space in the current buffer, the pool replenishes its internal // buffer with new memory to satisfy the request. This class is // *exception* *neutral*: If memory cannot be allocated, the behavior is // defined by the (optional) allocator specified at construction. // PRIVATE TYPES struct Block { // This 'struct' overlays the beginning of each managed block of // allocated memory, implementing a singly-linked list of managed // blocks, and thereby enabling constant-time additions to the list of // blocks. Block *d_next_p; // next pointer bsls::AlignmentUtil::MaxAlignedType d_memory; // force alignment }; enum { k_NUM_GEOMETRIC_BIN = sizeof(bsls::Types::size_type) > 4 ? 56 : 31 // number of bins available for // geometric growth strategy }; typedef bsl::uint64_t uint64_t; // to support old toolchains // DATA BufferManager d_bufferManager; // memory manager for // current buffer Block *d_head_p; // address of 1st block of // memory (or 0) Block **d_freeListPrevAddr_p; // address of the pointer // to the next block of // memory available for // use (which may be 0) char *d_geometricBin[k_NUM_GEOMETRIC_BIN]; // memory allocated for // geometric growth // strategy uint64_t d_alwaysUnavailable; // bitmask of bins never // available to supply // memory (reflects the // effects of // 'initialSize' and // 'maxBufferSize') uint64_t d_unavailable; // bitmask of bins // unavailable for // supplying memory uint64_t d_allocated; // bitmask of bins with // allocated memory Block *d_largeBlockList_p; // address of 1st block of // memory used to satisfy // allocations not handled // by other strategies (or // 0) const bsls::Types::size_type d_constantGrowthSize; // available size from an // allocated block when // using constant growth // and 0 when using // geometric growth bslma::Allocator *d_allocator_p; // memory allocator (held, // not owned) private: // PRIVATE MANIPULATORS void *allocateNonFastPath(bsls::Types::size_type size); // If the specified 'size' is not 0, use the allocator supplied at // construction to allocate a new internal buffer and return the // address of a contiguous block of memory of 'size' (in bytes) from // this new buffer, according to the alignment strategy specified at // construction. If 'size' is 0, no memory is allocated and 0 is // returned. // NOT IMPLEMENTED SequentialPool(const SequentialPool&); SequentialPool& operator=(const SequentialPool&); public: // CREATORS explicit SequentialPool(bslma::Allocator *basicAllocator = 0); explicit SequentialPool(bsls::BlockGrowth::Strategy growthStrategy, bslma::Allocator *basicAllocator = 0); explicit SequentialPool(bsls::Alignment::Strategy alignmentStrategy, bslma::Allocator *basicAllocator = 0); SequentialPool(bsls::BlockGrowth::Strategy growthStrategy, bsls::Alignment::Strategy alignmentStrategy, bslma::Allocator *basicAllocator = 0); // Create a sequential pool for allocating memory blocks from a // sequence of dynamically-allocated buffers. Optionally specify a // 'basicAllocator' used to supply memory for the dynamically-allocated // buffers. If 'basicAllocator' is 0, the currently installed default // allocator is used. Optionally specify a 'growthStrategy' used to // control buffer growth. If no 'growthStrategy' is specified, // geometric growth is used. Optionally specify an 'alignmentStrategy' // used to control alignment of allocated memory blocks. If no // 'alignmentStrategy' is specified, natural alignment is used. An // implementation-defined value is used as the initial size of the // internal buffer. Note that no limit is imposed on the size of the // internal buffers when geometric growth is used. Also note that when // constant growth is used, the size of the internal buffers will // always be the same as the implementation-defined value. explicit SequentialPool(int initialSize); explicit SequentialPool(bsls::Types::size_type initialSize, bslma::Allocator *basicAllocator = 0); SequentialPool(bsls::Types::size_type initialSize, bsls::BlockGrowth::Strategy growthStrategy, bslma::Allocator *basicAllocator = 0); SequentialPool(bsls::Types::size_type initialSize, bsls::Alignment::Strategy alignmentStrategy, bslma::Allocator *basicAllocator = 0); SequentialPool(bsls::Types::size_type initialSize, bsls::BlockGrowth::Strategy growthStrategy, bsls::Alignment::Strategy alignmentStrategy, bslma::Allocator *basicAllocator = 0); // Create a sequential pool for allocating memory blocks from a // sequence of dynamically-allocated buffers, of which the initial // buffer has the specified 'initialSize' (in bytes). Optionally // specify a 'basicAllocator' used to supply memory for the // dynamically-allocated buffers. If 'basicAllocator' is 0, the // currently installed default allocator is used. Optionally specify a // 'growthStrategy' used to control buffer growth. If no // 'growthStrategy' is specified, geometric growth is used. Optionally // specify an 'alignmentStrategy' used to control alignment of // allocated memory blocks. If no 'alignmentStrategy' is specified, // natural alignment is used. By specifying an 'initialSize', the // construction of a sequential pool will incur a memory allocation. // The behavior is undefined unless '0 < initialSize'. Note that no // limit is imposed on the size of the internal buffers when geometric // growth is used. Also note that when constant growth is used, the // size of the internal buffers will always be the same as // 'initialSize'. Also note that 'SequentialPool(int initialSize)' is // provided to avoid ambiguous definitions. SequentialPool(bsls::Types::size_type initialSize, bsls::Types::size_type maxBufferSize, bslma::Allocator *basicAllocator = 0); SequentialPool(bsls::Types::size_type initialSize, bsls::Types::size_type maxBufferSize, bsls::BlockGrowth::Strategy growthStrategy, bslma::Allocator *basicAllocator = 0); SequentialPool(bsls::Types::size_type initialSize, bsls::Types::size_type maxBufferSize, bsls::Alignment::Strategy alignmentStrategy, bslma::Allocator *basicAllocator = 0); SequentialPool(bsls::Types::size_type initialSize, bsls::Types::size_type maxBufferSize, bsls::BlockGrowth::Strategy growthStrategy, bsls::Alignment::Strategy alignmentStrategy, bslma::Allocator *basicAllocator = 0); // Create a sequential pool for allocating memory blocks from a // sequence of dynamically-allocated buffers, of which the initial // buffer has the specified 'initialSize' (in bytes), and the internal // buffer growth is limited to the specified 'maxBufferSize'. // Optionally specify a 'basicAllocator' used to supply memory for the // dynamically-allocated buffers. If 'basicAllocator' is 0, the // currently installed default allocator is used. Optionally specify a // 'growthStrategy' used to control buffer growth. If no // 'growthStrategy' is specified, geometric growth is used. Optionally // specify an 'alignmentStrategy' used to control alignment of // allocated memory blocks. If no 'alignmentStrategy' is specified, // natural alignment is used. The behavior is undefined unless // '0 < initialSize' and 'initialSize <= maxBufferSize'. Note that // when constant growth is used, the size of the internal buffers will // always be the same as 'initialSize'. SequentialPool(bsls::Types::size_type initialSize, bsls::Types::size_type maxBufferSize, bsls::BlockGrowth::Strategy growthStrategy, bsls::Alignment::Strategy alignmentStrategy, bool allocateInitialBuffer, bslma::Allocator *basicAllocator = 0); // Create a sequential pool for allocating memory blocks from a // sequence of dynamically-allocated buffers, of which the initial // buffer has the specified 'initialSize' (in bytes), the internal // buffer growth is limited to the specified 'maxBufferSize', the // specified 'growthStrategy' is used to control buffer growth, and the // specified 'alignmentStrategy' is used to control alignment of // allocated memory blocks. Allocate the initial buffer only if the // specified 'allocateInitialBuffer' is 'true'. Optionally specify a // 'basicAllocator' used to supply memory for the dynamically-allocated // buffers. If 'basicAllocator' is 0, the currently installed default // allocator is used. The behavior is undefined unless // '0 < initialSize' and 'initialSize <= maxBufferSize'. Note that // when constant growth is used, the size of the internal buffers will // always be the same as 'initialSize'. ~SequentialPool(); // Destroy this sequential pool. All memory allocated by this pool is // released. // MANIPULATORS void *allocate(bsls::Types::size_type size); // Return the address of a contiguous block of memory of the specified // 'size' (in bytes) according to the alignment strategy specified at // construction. If 'size' is 0, no memory is allocated and 0 is // returned. If the allocation request exceeds the remaining free // memory space in the current internal buffer, use the allocator // supplied at construction to allocate a new internal buffer, then // allocate memory from the new buffer. void *allocateAndExpand(bsls::Types::size_type *size); // Return the address of a contiguous block of memory of at least the // specified '*size' (in bytes), and load the actual amount of memory // allocated in '*size'. If '*size' is 0, return 0 with no effect. If // the allocation request exceeds the remaining free memory space in // the current internal buffer, use the allocator supplied at // construction to allocate a new internal buffer, then allocate memory // from the new buffer. template <class TYPE> void deleteObjectRaw(const TYPE *object); // Destroy the specified 'object'. Note that memory associated with // 'object' is not deallocated because there is no 'deallocate' method // in 'SequentialPool'. template <class TYPE> void deleteObject(const TYPE *object); // Destroy the specified 'object'. Note that this method has the same // effect as the 'deleteObjectRaw' method (since no deallocation is // involved), and exists for consistency across pools. void release(); // Release all memory allocated through this pool and return to the // underlying allocator *all* memory. The pool is reset to its // default-constructed state, retaining the alignment and growth // strategies, and the initial and maximum buffer sizes in effect // following construction. The effect of subsequently - to this // invokation of 'release' - using a pointer obtained from this object // prior to this call to 'release' is undefined. void rewind(); // Release all memory allocated through this pool and return to the // underlying allocator *only* memory that was allocated outside of the // typical internal buffer growth of this pool (i.e., large blocks). // All retained memory will be used to satisfy subsequent allocations. // The effect of subsequently - to this invokation of 'rewind' - using // a pointer obtained from this object prior to this call to 'rewind' // is undefined. void reserveCapacity(bsls::Types::size_type numBytes); // Reserve sufficient memory to satisfy allocation requests for at // least the specified 'numBytes' without replenishment (i.e., without // dynamic allocation). If 'numBytes' is 0, no memory is reserved. // Note that, when the 'numBytes' is distributed over multiple // 'allocate' requests - due to alignment effects - it is possible that // not all 'numBytes' of memory will be used for allocation before // triggering dynamic allocation. bsls::Types::size_type truncate(void *address, bsls::Types::size_type originalSize, bsls::Types::size_type newSize); // Reduce the amount of memory allocated at the specified 'address' of // the specified 'originalSize' (in bytes) to the specified 'newSize'. // Return 'newSize' after truncating, or 'originalSize' if the memory // block at 'address' cannot be truncated. This method can only // 'truncate' the memory block returned by the most recent 'allocate' // request from this memory pool, and otherwise has no effect. The // behavior is undefined unless the memory block at 'address' was // originally allocated by this memory pool, the size of the memory // block at 'address' is 'originalSize', 'newSize <= originalSize', and // 'release' was not called after allocating the memory block at // 'address'. // Aspects bslma::Allocator *allocator() const; // Return the allocator used by this object to allocate memory. Note // that this allocator can not be used to deallocate memory // allocated through this pool. }; } // close package namespace } // close enterprise namespace // Note that the 'new' and 'delete' operators are declared outside the // 'BloombergLP' namespace so that they do not hide the standard placement // 'new' and 'delete' operators (i.e., // 'void *operator new(bsl::size_t, void *)' and // 'void operator delete(void *)'). // // Also note that only the scalar versions of operators 'new' and 'delete' are // provided, because overloading 'new' (and 'delete') with their array versions // would cause dangerous ambiguity. Consider what would have happened had we // overloaded the array version of operator 'new': //.. // void *operator new[](bsl::size_t size, // BloombergLP::bdlma::SequentialPool& pool); //.. // The user of the pool class would have expected to be able to use operator // 'new' as follows: //.. // new (*pool) my_Type[...]; //.. // The problem is that this expression returns an array that cannot be safely // deallocated. On the one hand, there is no syntax in C++ to invoke an // overloaded 'operator delete'; on the other hand, the pointer returned by // operator 'new' cannot be passed to the 'deallocate' method directly because // the pointer is different from the one returned by the 'allocate' method. // The compiler offsets the value of this pointer by a header, which is used to // maintain the number of objects in the array (so that the 'operator delete' // can destroy the right number of objects). // FREE OPERATORS void *operator new(bsl::size_t size, BloombergLP::bdlma::SequentialPool& pool); // Return a block of memory of the specified 'size' (in bytes) allocated // from the specified 'pool'. Note that an object may allocate additional // memory internally, requiring the allocator to be passed in as a // constructor argument: //.. // my_Type *newMyType(bdlma::SequentialPool *pool, // bslma::Allocator *basicAllocator) // { // return new (*pool) my_Type(..., basicAllocator); // } //.. // Also note that the analogous version of operator 'delete' should not be // called directly. Instead, this component provides a static template // member function, 'deleteObject', parameterized by 'TYPE' that performs // the following: //.. // void deleteMyType(bdlma::SequentialPool *pool, my_Type *t) // { // t->~my_Type(); // } //.. void operator delete(void *address, BloombergLP::bdlma::SequentialPool& pool); // Use the specified 'pool' to deallocate the memory at the specified // 'address'. The behavior is undefined unless 'address' was allocated // using 'pool' and has not already been deallocated. This operator is // supplied solely to allow the compiler to arrange for it to be called in // case of an exception. // ============================================================================ // INLINE DEFINITIONS // ============================================================================ namespace BloombergLP { namespace bdlma { // -------------------- // class SequentialPool // -------------------- // CREATORS inline SequentialPool::~SequentialPool() { release(); } // MANIPULATORS inline void *SequentialPool::allocate(bsls::Types::size_type size) { void *result = d_bufferManager.allocate(size); if (BSLS_PERFORMANCEHINT_PREDICT_LIKELY(result)) { return result; // RETURN } return allocateNonFastPath(size); } inline void *SequentialPool::allocateAndExpand(bsls::Types::size_type *size) { BSLS_ASSERT(size); void *result = allocate(*size); if (BSLS_PERFORMANCEHINT_PREDICT_LIKELY(result)) { *size = d_bufferManager.expand(result, *size); } return result; } template <class TYPE> inline void SequentialPool::deleteObjectRaw(const TYPE *object) { if (0 != object) { #ifndef BSLS_PLATFORM_CMP_SUN object->~TYPE(); #else const_cast<TYPE *>(object)->~TYPE(); #endif } } template <class TYPE> inline void SequentialPool::deleteObject(const TYPE *object) { deleteObjectRaw(object); } inline bsls::Types::size_type SequentialPool::truncate( void *address, bsls::Types::size_type originalSize, bsls::Types::size_type newSize) { BSLS_ASSERT(address); BSLS_ASSERT(newSize <= originalSize); return d_bufferManager.truncate(address, originalSize, newSize); } // Aspects inline bslma::Allocator *SequentialPool::allocator() const { return d_allocator_p; } } // close package namespace } // close enterprise namespace // FREE OPERATORS inline void *operator new(bsl::size_t size, BloombergLP::bdlma::SequentialPool& pool) { return pool.allocate(size); } inline void operator delete(void *, BloombergLP::bdlma::SequentialPool&) { // NOTE: there is no deallocation from this allocation mechanism. } #endif // ---------------------------------------------------------------------------- // Copyright 2016 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 ----------------------------------