// bslma_sequentialpool.h -*-C++-*- #ifndef INCLUDED_BSLMA_SEQUENTIALPOOL #define INCLUDED_BSLMA_SEQUENTIALPOOL #include <bsls_ident.h> BSLS_IDENT("$Id: $") //@PURPOSE: Provide fast variable-size memory pool with allocation methods. // //@INTERNAL_DEPRECATED: Use 'bdlma_sequentialpool' instead. // //@CLASSES: // bslma::SequentialPool: fast variable-size memory pool // //@SEE_ALSO: bdlma_sequentialpool // //@DESCRIPTION: This component implements a memory pool, // 'bslma::SequentialPool', that dispenses memory blocks of any requested size // from an internal buffer or an optional user-supplied buffer. If an // allocation request exceeds the remaining free memory space in the pool, 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. By default, buffer // growth is not capped. The 'release' method releases all memory allocated // through this pool, as does the destructor. Note, however, that individual // allocated blocks of memory cannot be separately deallocated. // ///Alignment Strategy ///------------------ // The 'bslma::SequentialPool' allocates memory using one of the two alignment // strategies (defined in 'bslma_bufferallocator') optionally specified at // construction: 1) MAXIMUM ALIGNMENT or 2) NATURAL ALIGNMENT. // //: 1 MAXIMUM ALIGNMENT: This strategy always allocates memory aligned with the //: most restrictive alignment on the host platform. The value is defined by //: 'bsls::AlignmentUtil::BSLS_MAX_ALIGNMENT'. //: //: 2 NATURAL ALIGNMENT: This strategy allocates memory whose alignment depends //: on the requested number of bytes. An instance of a fundamental type //: ('int', etc.) is *naturally* *aligned* when it's size evenly divides its //: address. An instance of an aggregate type has natural alignment if the //: alignment of the most-restrictively aligned sub-object evenly divides the //: address of the aggregate. Natural alignment is always at least as //: restrictive as the compiler's required alignment. When only the size of //: an aggregate is known, and not its composition, we compute the alignment //: by finding the largest integral power of 2 (up to and including //: 'bsls::AlignmentUtil::BSLS_MAX_ALIGNMENT') that divides the requested //: (non-zero) number of bytes. This computed alignment is guaranteed to be //: at least as restrictive as any sub-object within the aggregate. // // The default strategy is NATURAL ALIGNMENT. // ///Optional 'buffer' Parameter ///--------------------------- // A buffer can be supplied to a 'bslma::SequentialPool' object at construction // in which case the pool will try to satisfy allocation requests using this // buffer before switching to a dynamically-allocated internal pool. Once the // object is using an internal pool, it will not try to satisfy any subsequent // allocation requests from the supplied buffer. Note that the pool does *not* // take ownership of the buffer. Also note that 'bufferSize' may be specified // using a positive or negative value to indicate a buffer growth strategy (see // "Internal Buffer Growth"). // ///Optional 'initialSize' Parameter ///-------------------------------- // In lieu of an externally-supplied buffer, a value for the 'initialSize' // parameter may be supplied at construction to specify the initial size of the // internal pool. If neither a buffer nor an 'initialSize' is specified, an // implementation-defined value is used for an initial size of the internal // pool. Note that 'initialSize' may be specified using a positive or negative // value to indicate a buffer growth strategy (see "Internal Buffer Growth"). // ///Internal Buffer Growth ///---------------------- // A 'bslma::SequentialPool' replenishes its internal buffer if the current // buffer cannot satisfy an allocation request. It does so by one of two // growth strategies: // //: Constant Growth: The new buffer is always of the same size as the current //: buffer (possibly supplied at construction). //: //: Geometric Growth: The new buffer will be geometrically larger than the //: current buffer up to an optionally-specified maximum limit. // // If a 'bufferSize' (and corresponding 'buffer') or 'initialSize' is supplied // at construction, the sign of its value implicitly specifies which growth // strategy to use. A positive value indicates Constant Growth, whereas a a // negative value indicates Geometric Growth. If neither 'bufferSize' nor // 'initialSize' is supplied, Geometric Growth is used. The optional // 'maxBufferSize' parameter may be used to place a cap on Geometric Growth // ('maxBufferSize' is ignored if Constant Growth is in effect). If no value // is specified for 'maxBufferSize', there is no cap on Geometric Growth. Note // that 'reserveCapacity' always ensures that the requested number of bytes is // available (allocating a new internal pool if necessary) irrespective of // whether the size of the request exceeds 'maxBufferSize'. // ///Usage ///----- // The 'bslma::SequentialPool' can be used to allocate memory for containers of // non-homogeneous elements, such as 'MyList' below. Note that the use of a // sequential pool allows the 'operator=' and 'removeAll' methods to quickly // deallocate memory of all elements by calling the 'release' method of the // pool. Similarly, the destructor of 'MyList' simply allows the pool's // destructor to deallocate memory for all elements: //.. // // MyList.h // #include <bsls_types.h> // #include <bslma_sequentialpool.h> // // namespace bslma { class Allocator; } // // class MyList { // char *d_typeArray_p; // void **d_list_p; // int d_length; // int d_size; // bslma::Allocator *d_allocator_p; // bslma::SequentialPool d_pool; // // // NOT IMPLEMENTED // MyList(const MyList&); // // private: // MyList(char* buffer, int bufferSize, bslma::Allocator *basicAllocator); // void increaseSize(); // // public: // enum Type { INT, DOUBLE, INT64 }; // // MyList(bslma::Allocator *basicAllocator); // // ~MyList(); // MyList& operator=(const MyList& rhs); // void append(int value); // void append(double value); // void append(bsls::Types::Int64 value); // void removeAll(); // // const int *theInt(int index) const; // const double *theDouble(int index) const; // const bsls::Types::Int64 *theInt64(int index) const; // const Type type(int index) const; // int length() const; // }; // // inline // void MyList::removeAll() // { // d_pool.release(); // d_length = 0; // } // // inline // const int *MyList::theInt(int index) const // { // return (int *) d_list_p[index]; // } // // inline // const double *MyList::theDouble(int index) const // { // return (double *) d_list_p[index]; // } // // inline // const bsls::Types::Int64 *MyList::theInt64(int index) const // { // return (bsls::Types::Int64 *) d_list_p[index]; // } // // inline // const MyList::Type MyList::type(int index) const // { // return (Type) d_typeArray_p[index]; // } // // inline // int MyList::length() const // { // return d_length; // } // // // ... // // // MyList.cpp // #include <MyList.h> // #include <bslma_allocator.h> // // enum { INITIAL_SIZE = 1, GROW_FACTOR = 2 }; // // static // void copyElement(void **list, MyList::Type type, int index, // void *srcElement, bslma::SequentialPool *pool) // // Copy the value of the specified 'srcElement' of the specified 'type' // // to the specified 'index' position in the specified 'list'. Use the // // specified 'pool' to supply memory. // { // assert(list); // assert(0 <= index); // assert(srcElement); // assert(pool); // // typedef bsls::Types::Int64 Int64; // // switch (type) { // case MyList::INT: // list[index] = new(pool->allocate(sizeof(int))) // int(*((int *) srcElement)); // break; // case MyList::DOUBLE: // list[index] = new(pool->allocate(sizeof(double))) // double(*((double *) srcElement)); // break; // case MyList::INT64: // list[index] = new(pool->allocate(sizeof(Int64))) // Int64(*((Int64 *) srcElement)); // break; // default: // assert(0 && "ERROR (MyList): Invalid element type."); // } // } // // static // void reallocate(void ***list, char **typeArray, int *size, // int newSize, int length, bslma::Allocator *basicAllocator) // // Reallocate memory in the specified 'list' and 'typeArray' using the // // specified 'basicAllocator' and update the specified size to the // // specified 'newSize'. The specified 'length' number of leading // // elements are preserved in 'list' and 'typeArray'. If 'allocate' // // should throw an exception, this function has no effect. The // // behavior is undefined unless 1 <= newSize, 0 <= length, and // // newSize <= length. // { // assert(list); // assert(*list); // assert(typeArray); // assert(*typeArray); // assert(size); // assert(1 <= newSize); // assert(0 <= length); // assert(length <= *size); // sanity check // assert(length <= newSize); // ensure class invariant // assert(basicAllocator); // // void **newList = // (void **) basicAllocator->allocate(newSize * sizeof *newList); // char *newTypeArray = // (char *) basicAllocator->allocate(newSize * sizeof *newTypeArray); // memcpy(newList, *list, length * sizeof **list); // memcpy(newTypeArray, *typeArray, length * sizeof **typeArray); // basicAllocator->deallocate(*list); // basicAllocator->deallocate(*typeArray); // *list = newList; // *typeArray = newTypeArray; // *size = newSize; // } // // void MyList::increaseSize() // { // int newSize = d_size * GROW_FACTOR; // reallocate(&d_list_p, &d_typeArray_p, &d_size, newSize, // d_length, d_allocator_p); // } // // MyList::MyList(char* buffer, int bufferSize, // bslma::Allocator *basicAllocator) // : d_length() // , d_size(MY_INITIAL_SIZE) // , d_pool(buffer, bufferSize, basicAllocator) // , d_allocator_p(basicAllocator) // { // assert(d_allocator_p); // // d_typeArray_p = // (char *) d_allocator_p->allocate(d_size * sizeof *d_typeArray_p); // d_list_p = // (void **) d_allocator_p->allocate(d_size * sizeof *d_list_p); // } // // MyList::MyList(bslma::Allocator *basicAllocator) // : d_size(INITIAL_SIZE) // , d_length(0) // , d_pool(basicAllocator) // , d_allocator_p(basicAllocator) // { // assert(d_allocator_p); // // d_typeArray_p = // (char *) d_allocator_p->allocate(d_size * sizeof *d_typeArray_p); // d_list_p = // (void **) d_allocator_p->allocate(d_size * sizeof *d_list_p); // } // // MyList::~MyList() // { // assert(d_typeArray_p); // assert(d_list_p); // assert(0 <= d_size); // assert(0 <= d_length); assert(d_length <= d_size); // assert(d_allocator_p); // // d_allocator_p->deallocate(d_typeArray_p); // d_allocator_p->deallocate(d_list_p); // } // // MyList& MyList::operator=(const MyList& rhs) // { // if (&rhs != this) { // // not aliased // d_pool.release(); // d_length = 0; // // int newLength = rhs.d_length; // if (newLength > d_size) { // reallocate(&d_list_p, &d_typeArray_p, &d_size, // newLength, d_length, d_allocator_p); // } // for (int i = 0; i < newLength; ++i) { // d_typeArray_p[i] = rhs.d_typeArray_p[i]; // copyElement(d_list_p, (Type) d_typeArray_p[i], i, // rhs.d_list_p[i], &d_pool); // } // d_length = newLength; // } // return *this; // } // // void MyList::append(int value) // { // if (d_length >= d_size) { // increaseSize(); // } // int *item = (int *) d_pool.allocate(sizeof *item); // *item = value; // d_typeArray_p[d_length] = (char) MyList::INT; // d_list_p[d_length++] = item; // } // // void MyList::append(double value) // { // if (d_length >= d_size) { // increaseSize(); // } // double *item = (double *) d_pool.allocate(sizeof *item); // *item = value; // d_typeArray_p[d_length] = (char) MyList::DOUBLE; // d_list_p[d_length++] = item; // } // // void MyList::append(bsls::Types::Int64 value) // { // typedef bsls::Types::Int64 Int64; // // if (d_length >= d_size) { // increaseSize(); // } // Int64 *item = (Int64 *) d_pool.allocate(sizeof *item); // *item = value; // d_typeArray_p[d_length] = (char) MyList::INT64; // d_list_p[d_length++] = item; // } //.. #ifdef BDE_OPENSOURCE_PUBLICATION // DEPRECATED #error "bslma_sequentialpool is deprecated" #endif #include <bslscm_version.h> #include <bslma_bufferallocator.h> #include <bslma_infrequentdeleteblocklist.h> #include <bsls_platform.h> #include <cstddef> // for 'std::size_t' namespace BloombergLP { namespace bslma { // ==================== // class SequentialPool // ==================== class SequentialPool { // This class implements a memory pool that dispenses arbitrarily-sized // blocks of memory from an internal buffer or an optionally user-supplied // buffer. If an allocation request exceeds the remaining free memory // space in the current 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. By default, buffer growth is not capped. The // 'release' method releases all memory allocated through this pool, as // does the destructor. Note, however, that individual allocated blocks of // memory cannot be individually deallocated. // TYPES enum GrowthStrategy { // Enumerate the various internal buffer growth strategies. CONSTANT, // constant growth GEOMETRIC // geometric growth }; // DATA char *d_buffer; // holds current free memory // buffer int d_cursor; // position of the next // available byte int d_bufSize; // current free memory buffer // size BufferAllocator::AlignmentStrategy d_alignmentStrategy; // alignment strategy int d_maxBufferSize; // maximum buffer size GrowthStrategy d_growthStrategy; // growth strategy InfrequentDeleteBlockList d_blockList; // provides free memory // NOT IMPLEMENTED SequentialPool(const SequentialPool&); SequentialPool& operator=(const SequentialPool&); private: // PRIVATE ACCESSORS int calculateNextBufferSize(int size) const; // Calculate and return the next buffer size corresponding to a reserve // or allocation of the specified 'size' bytes. public: // CREATORS explicit SequentialPool(Allocator *basicAllocator = 0); explicit SequentialPool( BufferAllocator::AlignmentStrategy strategy, Allocator *basicAllocator = 0); explicit SequentialPool(int initialSize, Allocator *basicAllocator = 0); SequentialPool(int initialSize, BufferAllocator::AlignmentStrategy strategy, Allocator *basicAllocator = 0); // Create a sequential pool for allocating memory blocks from an // internal buffer. Optionally specify an alignment 'strategy' used to // align allocated memory blocks. If 'strategy' is not specified, // *Natural Alignment* is used. Optionally specify an 'initialSize' // the absolute value of which indicates the initial size (in bytes) // for the internal buffer. If 'initialSize' is not specified, an // implementation-defined value is used. Optionally specify a // 'basicAllocator' used to supply memory. If 'basicAllocator' is 0, // the currently installed default allocator is used. If an 'allocate' // or 'reserveCapacity' request cannot be satisfied from the current // buffer, a new buffer is allocated, the size of which is determined // by a buffer growth strategy implied by 'initialSize'. If // 'initialSize' was specified and is negative, or if it was *not* // specified, the buffer growth strategy used is *Geometric Growth*; // otherwise it is *Constant Growth*. (See the component level // documentation for further details.) In either case, the new buffer // will have sufficient capacity to satisfy the request. If *Geometric // Growth* is in effect, no limit is imposed on the size of buffers. SequentialPool(char *buffer, int bufferSize, Allocator *basicAllocator = 0); SequentialPool(char *buffer, int bufferSize, BufferAllocator::AlignmentStrategy strategy, Allocator *basicAllocator = 0); // Create a sequential pool for allocating memory blocks initially from // the specified 'buffer' the size (in bytes) of which is indicated by // the absolute value of the specified 'bufferSize'. Optionally // specify an alignment 'strategy' used to align allocated memory // blocks. If 'strategy' is not specified, *Natural Alignment* is // used. Optionally specify a 'basicAllocator' used to supply memory. // If 'basicAllocator' is 0, the currently installed default allocator // is used. If an 'allocate' or 'reserveCapacity' request cannot be // satisfied from the current buffer, a new buffer is allocated, the // size of which is determined by a buffer growth strategy implied by // 'bufferSize'. If 'bufferSize' is negative, the buffer growth // strategy used is *Geometric Growth*; otherwise it is *Constant // Growth*. (See the component level documentation for further // details.) In either case, the new buffer will have sufficient // capacity to satisfy the request. If *Geometric Growth* is in // effect, no limit is imposed on the size of buffers. SequentialPool(int initialSize, int maxBufferSize, Allocator *basicAllocator = 0); SequentialPool(int initialSize, int maxBufferSize, BufferAllocator::AlignmentStrategy strategy, Allocator *basicAllocator = 0); // Create a sequential pool for allocating memory blocks from an // internal buffer the initial size (in bytes) of which is indicated by // the absolute value of the specified 'initialSize'. The specified // 'maxBufferSize' indicates the maximum size (in bytes) allowed for // internally allocated buffers. Optionally specify an alignment // 'strategy' used to align allocated memory blocks. If 'strategy' is // not specified, *Natural Alignment* is used. Optionally specify a // 'basicAllocator' used to supply memory. If 'basicAllocator' is 0, // the currently installed default allocator is used. If an 'allocate' // or 'reserveCapacity' request cannot be satisfied from the current // buffer, a new buffer is allocated, the size of which is determined // by a buffer growth strategy implied by 'initialSize'. If // 'initialSize' is negative the buffer growth strategy used is // *Geometric Growth*; otherwise it is *Constant Growth*. (See the // component level documentation for further details.) In either case, // the new buffer will have sufficient capacity to satisfy the request. // If *Geometric Growth* is in effect, the geometric progression of // buffer sizes is capped at 'maxBufferSize'. The behavior is // undefined unless '0 < maxBufferSize', and // '|initialSize| <= maxBufferSize'. Note that 'maxBufferSize' is // ignored if 'initialSize > 0'. Also note that 'maxBufferSize' may be // overridden by a sufficiently large value passed to 'allocate' or // 'reserveCapacity'. SequentialPool(char *buffer, int bufferSize, int maxBufferSize, Allocator *basicAllocator = 0); SequentialPool(char *buffer, int bufferSize, int maxBufferSize, BufferAllocator::AlignmentStrategy strategy, Allocator *basicAllocator = 0); // Create a sequential pool for allocating memory blocks initially from // the specified 'buffer' the size (in bytes) of which is indicated by // the absolute value of the specified 'bufferSize'. The specified // 'maxBufferSize' indicates the maximum size (in bytes) allowed for // internally allocated buffers. Optionally specify an alignment // 'strategy' used to align allocated memory blocks. If 'strategy' is // not specified, *Natural Alignment* is used. Optionally specify a // 'basicAllocator' used to supply memory. If 'basicAllocator' is 0, // the currently installed default allocator is used. If an 'allocate' // or 'reserveCapacity' request cannot be satisfied from the current // buffer, a new buffer is allocated, the size of which is determined // by a buffer growth strategy implied by 'bufferSize'. If // 'bufferSize' is negative, the buffer growth strategy used is // *Geometric Growth*; otherwise it is *Constant Growth*. (See the // component level documentation for further details.) In either case, // the new buffer will have sufficient capacity to satisfy the request. // If *Geometric Growth* is in effect, the geometric progression of // buffer sizes is capped at 'maxBufferSize'. The behavior is // undefined unless '0 < maxBufferSize', and // '|bufferSize| <= maxBufferSize'. Note that 'maxBufferSize' is // ignored if 'bufferSize > 0'. Also note that 'maxBufferSize' may be // overridden by a sufficiently large value passed to 'allocate' or // 'reserveCapacity'. ~SequentialPool(); // Destroy this object and release all memory currently allocated // through this pool. // MANIPULATORS void *allocate(int size); // Return memory of the specified 'size'. If 'size' is 0, no memory is // allocated and 0 is returned. The behavior is undefined unless // '0 <= size'. void *allocateAndExpand(int *size); // Return memory of at least the specified '*size' and return the // actual amount of memory allocated in '*size'. If '*size' is 0, no // memory is allocated and 0 is returned. The behavior is undefined // unless '0 <= *size'. void *allocateAndExpand(int *size, int maxNumBytes); // Return memory of at least the specified '*size' and at most the // specified 'maxNumBytes'. Also return the actual amount of memory // allocated in '*size'. If '*size' is 0, no memory is allocated and 0 // is returned. The behavior is undefined unless // '0 <= *size <= maxNumBytes'. template <class TYPE> void deleteObject(const TYPE *object); // Destroy the specified 'object'. Note that this method is exactly // the same as the 'deleteObjectRaw' method since no deallocation is // involved. This method exists purely for consistency across pools. template <class TYPE> void deleteObjectRaw(const TYPE *object); // Destroy the specified 'object'. Note that the memory is not // deallocated because there is no 'deallocate' method in a // 'bslma_sequentialpool'. int expand(void *address, int originalNumBytes); // Increase the amount of memory allocated at the specified 'address' // from the specified 'originalNumBytes' to the maximum amount easily // obtainable. Return the amount of memory available at 'address' // after the expansion. The behavior is undefined unless the call to // this allocator that provided the 'address' was performed with the // 'originalNumBytes'. Note that this function will not expand the // memory unless there have been no allocations since the allocation // for 'originalNumBytes'. int expand(void *address, int originalNumBytes, int maxNumBytes); // Increase the amount of memory allocated at the specified 'address' // from the specified 'originalNumBytes' to the maximum amount easily // obtainable up to the specified 'maxNumBytes'. Return the amount of // memory available at 'address' after the expansion. The behavior is // undefined unless the call to this allocator that provided the // 'address' was performed with the 'originalNumBytes' and // 'originalNumBytes < maxNumBytes'. Note that this function will not // expand the memory unless there have been no allocations since the // allocation for 'originalNumBytes'. void release(); // Release all memory currently allocated through this pool. void reserveCapacity(int numBytes); // Reserve sufficient memory to satisfy allocation requests for at // least the specified 'numBytes' without replenishment (i.e., without // internal allocation). The behavior is undefined unless // '0 <= numBytes'. int truncate(void *address, int originalNumBytes, int newNumBytes); // Reduce the amount of memory allocated at the specified 'address' // from the specified 'originalNumBytes' to the specified // 'newNumBytes'. Return the amount of memory available at 'address' // after the truncation. The behavior is undefined unless the call to // this allocator that provided the 'address' was performed with the // 'originalNumBytes' and 'newNumBytes <= originalNumBytes'. Note that // this function will not truncate the memory unless there have been no // allocations since the allocation for 'originalNumBytes'. }; } // close package namespace } // close enterprise namespace // FREE OPERATORS // Note that the operators 'new' and 'delete' are declared outside the // 'BloombergLP' namespace so that they do not hide the standard placement // 'new' and 'delete' operators (i.e., 'void *operator new(size_t, void *)' and // 'void operator delete(void *)'). // // Note also 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[](std::size_t size, // BloombergLP::bslma::Pool& pool) //.. // The user of the pool class would have expected to be able to use // 'new-expression': //.. // 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 the // 'new-expression' 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 an extra header, // which the compiler uses to maintain the number of the objects in the array // (so that the 'delete-expression' knows how many objects it needs to // destroy). inline void *operator new(std::size_t size, BloombergLP::bslma::SequentialPool& pool); // Return the memory allocated from the specified 'pool'. The behavior is // undefined unless 'size' is the same as 'objectSize' that 'pool' has been // constructed with. Note that an object may allocate additional memory // internally, requiring the allocator to be passed in as a constructor // argument: //.. // my_Type *newMyType(bslma::Pool *pool, bslma::Allocator *basicAllocator) // { // return new (*pool) my_Type(..., basicAllocator); // } //.. // Note also 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(bslma::Pool *pool, my_Type *t) // { // t->~my_Type(); // pool->deallocate(t); // } //.. inline void operator delete(void *address, BloombergLP::bslma::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 bslma { // -------------- // SequentialPool // -------------- // CREATORS inline SequentialPool::~SequentialPool() { } // MANIPULATORS template <class TYPE> inline void SequentialPool::deleteObjectRaw(const TYPE *object) { if (0 != object) { #if defined(BSLS_PLATFORM_CMP_SUN) && BSLS_PLATFORM_CMP_VERSION < 0x5130 const_cast<TYPE *>(object)->~TYPE(); #else object->~TYPE(); #endif } } template <class TYPE> inline void SequentialPool::deleteObject(const TYPE *object) { deleteObjectRaw(object); } } // close package namespace #ifndef BDE_OPENSOURCE_PUBLICATION // BACKWARD_COMPATIBILITY // ============================================================================ // BACKWARD COMPATIBILITY // ============================================================================ typedef bslma::SequentialPool bslma_SequentialPool; // This alias is defined for backward compatibility. #endif // BDE_OPENSOURCE_PUBLICATION -- BACKWARD_COMPATIBILITY } // close enterprise namespace // FREE OPERATORS inline void *operator new(std::size_t size, BloombergLP::bslma::SequentialPool& pool) { return pool.allocate(static_cast<int>(size)); } inline void operator delete(void *, BloombergLP::bslma::SequentialPool&) { // NOTE: there is no deallocation from this allocation mechanism. } #endif // ---------------------------------------------------------------------------- // Copyright 2013 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 ----------------------------------