BDE 4.39.x Production Release
Loading...
Searching...
No Matches
bdlma_concurrentpool.h
Go to the documentation of this file.
1/// @file bdlma_concurrentpool.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bdlma_concurrentpool.h -*-C++-*-
8#ifndef INCLUDED_BDLMA_CONCURRENTPOOL
9#define INCLUDED_BDLMA_CONCURRENTPOOL
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bdlma_concurrentpool bdlma_concurrentpool
15/// @brief Provide thread-safe allocation of memory blocks of uniform size.
16/// @addtogroup bdl
17/// @{
18/// @addtogroup bdlma
19/// @{
20/// @addtogroup bdlma_concurrentpool
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bdlma_concurrentpool-purpose"> Purpose</a>
25/// * <a href="#bdlma_concurrentpool-classes"> Classes </a>
26/// * <a href="#bdlma_concurrentpool-description"> Description </a>
27/// * <a href="#bdlma_concurrentpool-configuration-at-construction"> Configuration at Construction </a>
28/// * <a href="#bdlma_concurrentpool-overloaded-global-operator-new"> Overloaded Global Operator new </a>
29/// * <a href="#bdlma_concurrentpool-usage"> Usage </a>
30/// * <a href="#bdlma_concurrentpool-example-1-basic-usage"> Example 1: Basic Usage </a>
31///
32/// # Purpose {#bdlma_concurrentpool-purpose}
33/// Provide thread-safe allocation of memory blocks of uniform size.
34///
35/// # Classes {#bdlma_concurrentpool-classes}
36///
37/// - bdlma::ConcurrentPool: thread-safe memory manager that allocates blocks
38///
39/// @see bdlma_pool
40///
41/// # Description {#bdlma_concurrentpool-description}
42/// This component implements a memory pool,
43/// `bdlma::ConcurrentPool`, that allocates and manages memory blocks of some
44/// uniform size specified at construction. A `bdlma::ConcurrentPool` object
45/// maintains an internal linked list of free memory blocks, and dispenses one
46/// block for each `allocate` method invocation. When a memory block is
47/// deallocated, it is returned to the free list for potential reuse.
48///
49/// Whenever the linked list of free memory blocks is depleted, the
50/// `bdlma::ConcurrentPool` replenishes the list by first allocating a large,
51/// contiguous "chunk" of memory, then splitting the chunk into multiple memory
52/// blocks. A chunk and its constituent memory blocks can be depicted visually:
53/// @code
54/// +-----+--- memory blocks of uniform size
55/// | |
56/// ----- ----- ------------
57/// | | | ... |
58/// =====^=====^============
59///
60/// \___________ __________/
61/// V
62/// a "chunk"
63/// @endcode
64/// Note that the size of the allocated chunk is determined by both the growth
65/// strategy and maximum blocks per chunk, either of which can be optionally
66/// specified at construction (see the "Configuration at Construction" section).
67///
68/// ## Configuration at Construction {#bdlma_concurrentpool-configuration-at-construction}
69///
70///
71/// When creating a `bdlma::ConcurrentPool`, clients must specify the specific
72/// block size managed and dispensed by the pool. Furthermore, clients can
73/// optionally configure:
74///
75/// 1. GROWTH STRATEGY -- geometrically growing chunk size starting from 1 (in
76/// terms of the number of memory blocks per chunk), or fixed chunk size. If
77/// the growth strategy is not specified, geometric growth is used.
78/// 2. MAX BLOCKS PER CHUNK -- the maximum number of memory blocks within a
79/// chunk. If the maximum blocks per chunk is not specified, an
80/// implementation-defined default value is used.
81/// 3. BASIC ALLOCATOR -- the allocator used to supply memory to replenish the
82/// internal pool. If not specified, the currently installed default
83/// allocator (see @ref bslma_default ) is used.
84///
85/// For example, if geometric growth is used and the maximum blocks per chunk is
86/// specified as 30, the chunk size grows geometrically, starting from 1, until
87/// the specified maximum blocks per chunk, as follows:
88/// @code
89/// 1, 2, 4, 8, 16, 30, 30, 30 ...
90/// @endcode
91/// If constant growth is used, the chunk size is always the specified maximum
92/// blocks per chunk (or an implementation-defined value if the maximum blocks
93/// per chunk is not specified), for example:
94/// @code
95/// 30, 30, 30 ...
96/// @endcode
97/// A default-constructed pool has an initial chunk size of 1 (i.e., the number
98/// of memory blocks of a given size allocated at once to replenish a pool's
99/// memory), and the pool's chunk size grows geometrically until it reaches an
100/// implementation-defined maximum, at which it is capped. Finally, unless
101/// otherwise specified, all memory comes from the allocator that was the
102/// currently installed default allocator at the time the
103/// `bdlma::ConcurrentPool` was created.
104///
105/// ## Overloaded Global Operator new {#bdlma_concurrentpool-overloaded-global-operator-new}
106///
107///
108/// This component overloads the global `operator new` to allow convenient
109/// syntax for the construction of objects using a `bdlma::ConcurrentPool`. The
110/// `new` operator supplied in this component takes a `bdlma::ConcurrentPool`
111/// argument indicating the source of the memory. Consider the following use of
112/// standard placement `new` syntax (supplied by `bsl_new.h`) along with a
113/// `bdlma::ConcurrentPool` to allocate an object of type `T`. Note that the
114/// size of `T` must be the same or smaller than the `blockSize` with which the
115/// pool is constructed:
116/// @code
117/// void f(bdlma::ConcurrentPool *pool)
118/// {
119/// assert(pool->blockSize() >= sizeof(T));
120///
121/// T *t = new (pool->allocate()) T(...);
122///
123/// // ...
124/// }
125/// @endcode
126/// This usage style is not exception-safe. If the constructor of `T` throws an
127/// exception, `pool->deallocate` is never called.
128///
129/// Supplying an overloaded global `operator new`:
130/// @code
131/// ::operator new(bsl::size_t size, bdlma::ConcurrentPool& pool);
132/// @endcode
133/// allows for the following cleaner usage, which does not require the size
134/// calculation and guarantees that `pool->deallocate` *is* called in case of an
135/// exception:
136/// @code
137/// void f(bdlma::ConcurrentPool *pool)
138/// {
139/// assert(pool->blockSize() >= sizeof(T));
140///
141/// T *t = new (*pool) T(...);
142///
143/// // ...
144/// @endcode
145/// Also note that the analogous version of operator `delete` should *not* be
146/// called directly. Instead, this component provides a static template member
147/// function `deleteObject`, parameterized on `TYPE`:
148/// @code
149/// pool->deleteObject(t);
150/// }
151/// @endcode
152/// The above `deleteObject` call is equivalent to performing the following:
153/// @code
154/// t->~TYPE();
155/// pool->deallocate(t);
156/// @endcode
157/// An overloaded operator `delete` is supplied solely to allow the compiler to
158/// arrange for it to be called in case of an exception.
159///
160/// ## Usage {#bdlma_concurrentpool-usage}
161///
162///
163/// This section illustrates intended use of this component.
164///
165/// ### Example 1: Basic Usage {#bdlma_concurrentpool-example-1-basic-usage}
166///
167///
168/// A `bdlma::ConcurrentPool` can be used by node-based containers (such as
169/// lists, trees, and hash tables that hold multiple elements of uniform size)
170/// for efficient memory allocation of new elements. The following container
171/// class, `my_PooledArray`, stores templatized values "out-of-place" as nodes
172/// in a `vector` of pointers. Since the size of each node is fixed and known
173/// *a priori*, the class uses a `bdlma::ConcurrentPool` to allocate memory for
174/// the nodes to improve memory allocation efficiency:
175/// @code
176/// // my_poolarray.h
177///
178/// template <class T>
179/// class my_PooledArray {
180/// // This class implements a container that stores 'double' values
181/// // out-of-place.
182///
183/// // DATA
184/// bsl::vector<T *> d_array_p; // array of pooled elements
185/// bdlma::ConcurrentPool d_pool; // memory manager for array elements
186///
187/// private:
188/// // Not implemented:
189/// my_PooledArray(const my_PooledArray&);
190///
191/// public:
192/// // CREATORS
193/// explicit my_PooledArray(bslma::Allocator *basicAllocator = 0);
194/// // Create a pooled array that stores the parameterized values
195/// // "out-of-place". Optionally specify a 'basicAllocator' used to
196/// // supply memory. If 'basicAllocator' is 0, the currently
197/// // installed default allocator is used.
198///
199/// ~my_PooledArray();
200/// // Destroy this array and all elements held by it.
201///
202/// // MANIPULATORS
203/// void append(const T &value);
204/// // Append the specified 'value' to this array.
205///
206/// void removeAll();
207/// // Remove all elements from this array.
208///
209/// // ACCESSORS
210/// int length() const;
211/// // Return the number of elements in this array.
212///
213/// const T& operator[](int index) const;
214/// // Return a reference to the non-modifiable value at the specified
215/// // 'index' in this array. The behavior is undefined unless
216/// // '0 <= index < length()'.
217/// };
218/// @endcode
219/// In the `removeAll` method, all elements are deallocated by invoking the
220/// pool's `release` method. This technique implies significant performance
221/// gain when the array contains many elements:
222/// @code
223/// // MANIPULATORS
224/// template <class T>
225/// inline
226/// void my_PooledArray<T>::removeAll()
227/// {
228/// d_array_p.clear();
229/// d_pool.release();
230/// }
231///
232/// // ACCESSORS
233/// template <class T>
234/// inline
235/// int my_PooledArray<T>::length() const
236/// {
237/// return static_cast<int>(d_array_p.size());
238/// }
239///
240/// template <class T>
241/// inline
242/// const T& my_PooledArray<T>::operator[](int index) const
243/// {
244/// assert(0 <= index);
245/// assert(index < length());
246///
247/// return *d_array_p[index];
248/// }
249/// @endcode
250/// Note that the growth strategy and maximum chunk size of the pool is left as
251/// the default value:
252/// @code
253/// // my_poolarray.cpp
254///
255/// // CREATORS
256/// template <class T>
257/// my_PooledArray<T>::my_PooledArray(bslma::Allocator *basicAllocator)
258/// : d_array_p(basicAllocator)
259/// , d_pool(sizeof(T), basicAllocator)
260/// {
261/// }
262/// @endcode
263/// Since all memory is managed by `d_pool`, we do not have to explicitly invoke
264/// `deleteObject` to reclaim outstanding memory. The destructor of the pool
265/// will automatically deallocate all array elements:
266/// @code
267/// template <class T>
268/// my_PooledArray<T>::~my_PooledArray()
269/// {
270/// // Elements are automatically deallocated when 'd_pool' is destroyed.
271/// }
272/// @endcode
273/// Note that the overloaded "placement" `new` is used to allocate new nodes:
274/// @code
275/// template <class T>
276/// void my_PooledArray<T>::append(const T& value)
277/// {
278/// T *tmp = new (d_pool) T(value);
279/// d_array_p.push_back(tmp);
280/// }
281/// @endcode
282/// @}
283/** @} */
284/** @} */
285
286/** @addtogroup bdl
287 * @{
288 */
289/** @addtogroup bdlma
290 * @{
291 */
292/** @addtogroup bdlma_concurrentpool
293 * @{
294 */
295
296#include <bdlscm_version.h>
297
298#include <bslmt_mutex.h>
299
301
302#include <bslma_allocator.h>
303#include <bslma_deleterhelper.h>
304
305#include <bsls_alignmentutil.h>
306#include <bsls_assert.h>
307#include <bsls_atomic.h>
309#include <bsls_blockgrowth.h>
310#include <bsls_platform.h>
311#include <bsls_types.h>
312
313#include <bsl_cstddef.h>
314
315
316namespace bdlma {
317
318 // ====================
319 // class ConcurrentPool
320 // ====================
321
322/// This class implements a memory pool that allocates and manages memory
323/// blocks of some uniform size specified at construction. This memory pool
324/// maintains an internal linked list of free memory blocks, and dispenses
325/// one block for each `allocate` method invocation. When a memory block is
326/// deallocated, it is returned to the free list for potential reuse.
327///
328/// This class guarantees thread safety while allocating or releasing
329/// memory.
330///
331/// See @ref bdlma_concurrentpool
333
334 // PRIVATE TYPES
335
336 /// This `struct` implements a link data structure that stores the
337 /// address of the next link, and is used to implement the internal linked list of free memory blocks.
338 ///
339 /// \note Note that this type is
340 /// replicated in `bdlma_concurrentpool.cpp` to provide access to a
341 /// compatible type from static methods defined in `bdema_pool.cpp`.
342 ///
343 /// See @ref bdlma_concurrentpool
344 struct Link {
345
346 union {
347 bsls::AtomicOperations::AtomicTypes::Int d_refCount;
349 };
350 Link *volatile d_next_p; // pointer to next link
351 };
352
353 // DATA
354 bsls::Types::size_type d_blockSize; // size of each allocated memory block
355 // returned to client
356
357 bsls::Types::size_type d_internalBlockSize;
358 // actual size of each block
359 // maintained on free list (contains
360 // overhead for 'Link')
361
362 int d_chunkSize; // current chunk size (in
363 // blocks-per-chunk)
364
365 int d_maxBlocksPerChunk;
366 // maximum chunk size (in
367 // blocks-per-chunk)
368
369 bsls::BlockGrowth::Strategy d_growthStrategy;
370 // growth strategy of the chunk size
371
372 bsls::AtomicPointer<Link> d_freeList;
373 // linked list of free memory blocks
374
376 // memory manager for allocated memory
377
378 bslmt::Mutex d_mutex; // protects access to the block list
379
380 // PRIVATE MANIPULATORS
381
382 /// Dynamically allocate a new chunk using the pool's underlying growth
383 /// strategy, and use the chunk to replenish the free memory list of this pool.
384 ///
385 /// \pre The behavior is undefined unless the calling thread has
386 /// a lock on `d_mutex`.
387 void replenish();
388
389 private:
390 // NOT IMPLEMENTED
392 ConcurrentPool& operator=(const ConcurrentPool&);
393
394 public:
395 // CREATORS
396
397 /// Create a memory pool that returns blocks of contiguous memory of the
398 /// specified `blockSize` (in bytes) for each `allocate` method
399 /// invocation. Optionally specify a `growthStrategy` used to control
400 /// the growth of internal memory chunks (from which memory blocks are
401 /// dispensed). If `growthStrategy` is not specified, geometric growth
402 /// is used. Optionally specify `maxBlocksPerChunk` as the maximum
403 /// chunk size. If geometric growth is used, the chunk size grows
404 /// starting at `blockSize`, doubling in size until the size is exactly
405 /// `blockSize * maxBlocksPerChunk`. If constant growth is used, the
406 /// chunk size is always `maxBlocksPerChunk`. If `maxBlocksPerChunk` is
407 /// not specified, an implementation-defined value is used. Optionally
408 /// specify a `basicAllocator` used to supply memory. If
409 /// `basicAllocator` is 0, the currently installed default allocator is used.
410 ///
411 /// \pre The behavior is undefined unless `1 <= blockSize` and
412 /// `1 <= maxBlocksPerChunk`.
414 bslma::Allocator *basicAllocator = 0);
416 bsls::BlockGrowth::Strategy growthStrategy,
417 bslma::Allocator *basicAllocator = 0);
419 bsls::BlockGrowth::Strategy growthStrategy,
420 int maxBlocksPerChunk,
421 bslma::Allocator *basicAllocator = 0);
422
423 /// Destroy this pool, releasing all associated memory back to the
424 /// underlying allocator.
426
427 // MANIPULATORS
428
429 /// Return the address of a contiguous block of memory having the fixed
430 /// block size specified at construction.
431 void *allocate();
432
433 /// Relinquish the memory block at the specified `address` back to this pool object for reuse.
434 ///
435 /// \pre The behavior is undefined unless `address`
436 /// is non-zero, was allocated by this pool, and has not already been
437 /// deallocated.
438 void deallocate(void *address);
439
440 /// Destroy the specified `object` based on its dynamic type and then
441 /// use this pool to deallocate its memory footprint. This method has no effect if `object` is 0.
442 ///
443 /// \pre The behavior is undefined unless
444 /// `object`, when cast appropriately to `void *`, was allocated using
445 /// this pool and has not already been deallocated.
446 ///
447 /// \note Note that `dynamic_cast<void *>(object)` is applied if `TYPE` is polymorphic,
448 /// and `static_cast<void *>(object)` is applied otherwise.
449 template <class TYPE>
450 void deleteObject(const TYPE *object);
451
452 /// Destroy the specified `object` and then use this pool to deallocate
453 /// its memory footprint. This method has no effect if `object` is 0.
454 ///
455 /// \pre The behavior is undefined unless `object` is **not** a secondary base
456 /// class pointer (i.e., the address is (numerically) the same as when
457 /// it was originally dispensed by this pool), was allocated using this
458 /// pool, and has not already been deallocated.
459 template <class TYPE>
460 void deleteObjectRaw(const TYPE *object);
461
462 /// Relinquish all memory currently allocated via this pool object.
463 void release();
464
465 /// Reserve memory from this pool to satisfy memory requests for at
466 /// least the specified `numBlocks` before the pool replenishes.
467 ///
468 /// \pre The behavior is undefined unless `0 <= numBlocks`.
469 void reserveCapacity(int numBlocks);
470
471 // ACCESSORS
472
473 /// Return the size (in bytes) of the memory blocks allocated from this pool object.
474 ///
475 /// \note Note that all blocks dispensed by this pool have the
476 /// same size.
478
479 // Aspects
480
481 /// Return the allocator used by this object to allocate memory.
482 ///
483 /// \note Note that this allocator can not be used to deallocate memory
484 /// allocated through this pool.
486};
487
488} // close package namespace
489
490
491// Note that the 'new' and 'delete' operators are declared outside the
492// 'BloombergLP' namespace so that they do not hide the standard placement
493// 'new' and 'delete' operators (i.e.,
494// 'void *operator new(bsl::size_t, void *)' and
495// 'void operator delete(void *)').
496//
497// Also note that only the scalar versions of operators 'new' and 'delete' are
498// provided, because overloading 'new' (and 'delete') with their array versions
499// would cause dangerous ambiguity. Consider what would have happened had we
500// overloaded the array version of 'operator new':
501//..
502// void *operator new[](bsl::size_t size, BloombergLP::bdlma::Pool& pool);
503//..
504// A user of 'bdlma::Pool' may expect to be able to use array 'operator new' as
505// follows:
506//..
507// new (*pool) my_Type[...];
508//..
509// The problem is that this expression returns an array that cannot be safely
510// deallocated. On the one hand, there is no syntax in C++ to invoke an
511// overloaded 'operator delete'; on the other hand, the pointer returned by
512// 'operator new' cannot be passed to the 'deallocate' method directly because
513// the pointer is different from the one returned by the 'allocate' method.
514// The compiler offsets the value of this pointer by a header, which is used to
515// maintain the number of objects in the array (so that 'operator delete' can
516// destroy the right number of objects).
517
518// FREE OPERATORS
519
520/// Return a block of memory of the specified `size` (in bytes) allocated from the specified `pool`.
521///
522/// \pre The behavior is undefined unless `size` is
523/// the same or smaller than the `blockSize` with which `pool` was constructed.
524///
525/// \note Note that an object may allocate additional memory
526void *operator new(bsl::size_t size, BloombergLP::bdlma::ConcurrentPool& pool);
527
528 // internally, requiring the allocator to be passed in as a constructor
529 // argument:
530 //..
531 // my_Type *newMyType(bdlma::ConcurrentPool *pool,
532 // bslma::Allocator *basicAllocator)
533 // {
534 // return new (*pool) my_Type(..., basicAllocator);
535 // }
536 //..
537 // Also note that the analogous version of 'operator delete' should not be
538 // called directly. Instead, this component provides a static template
539 // member function, 'deleteObject', parameterized by 'TYPE':
540 //..
541 // void deleteMyType(my_Type *t, bdlma::ConcurrentPool *pool)
542 // {
543 // pool->deleteObject(t);
544 // }
545 //..
546 // 'deleteObject' performs the following:
547 //..
548 // t->~my_Type();
549 // pool->deallocate(t);
550 //..
551
552/// Use the specified `pool` to deallocate the memory at the specified `address`.
553///
554/// \pre The behavior is undefined unless `address` was allocated
555/// using `pool` and has not already been deallocated. This operator is
556/// supplied solely to allow the compiler to arrange for it to be called in
557/// case of an exception. Client code should not call it; use
558/// `bdlma::ConcurrentPool::deleteObject()` instead.
559inline
560void operator delete(void *address, BloombergLP::bdlma::ConcurrentPool& pool);
561
562// ============================================================================
563// INLINE DEFINITIONS
564// ============================================================================
565
566
567namespace bdlma {
568
569 // --------------------
570 // class ConcurrentPool
571 // --------------------
572
573// MANIPULATORS
574template<class TYPE>
575inline
576void ConcurrentPool::deleteObject(const TYPE *object)
577{
579}
580
581template<class TYPE>
582inline
583void ConcurrentPool::deleteObjectRaw(const TYPE *object)
584{
586}
587
588inline
590{
591 d_mutex.lock();
592 d_freeList = (Link*)0;
593 d_blockList.release();
594 d_mutex.unlock();
595}
596
597// ACCESSORS
598inline
600{
601 return d_blockSize;
602}
603
604// Aspects
605
606inline
608{
609 return d_blockList.allocator();
610}
611
612} // close package namespace
613
614
615// FREE OPERATORS
616inline
617void *operator new(bsl::size_t size, BloombergLP::bdlma::ConcurrentPool& pool)
618{
619#if defined(BSLS_ASSERT_SAFE_IS_USED)
620 // gcc-4.8.1 introduced a new warning for unused typedefs, so this typedef
621 // should only be present in SAFE mode builds (where it is used).
622
623 typedef BloombergLP::bsls::AlignmentUtil Util;
624
625 BSLS_ASSERT_SAFE(size <= pool.blockSize()
626 && Util::calculateAlignmentFromSize(size)
627 <= Util::calculateAlignmentFromSize(pool.blockSize()));
628#endif
629
630 static_cast<void>(size); // suppress "unused parameter" warnings
631 return pool.allocate();
632}
633
634inline
635void operator delete(void *address, BloombergLP::bdlma::ConcurrentPool& pool)
636{
637 pool.deallocate(address);
638}
639
640#endif
641
642// ----------------------------------------------------------------------------
643// Copyright 2016 Bloomberg Finance L.P.
644//
645// Licensed under the Apache License, Version 2.0 (the "License");
646// you may not use this file except in compliance with the License.
647// You may obtain a copy of the License at
648//
649// http://www.apache.org/licenses/LICENSE-2.0
650//
651// Unless required by applicable law or agreed to in writing, software
652// distributed under the License is distributed on an "AS IS" BASIS,
653// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
654// See the License for the specific language governing permissions and
655// limitations under the License.
656// ----------------------------- END-OF-FILE ----------------------------------
657
658/** @} */
659/** @} */
660/** @} */
Definition bdlma_concurrentpool.h:332
void deleteObjectRaw(const TYPE *object)
Definition bdlma_concurrentpool.h:583
ConcurrentPool(bsls::Types::size_type blockSize, bsls::BlockGrowth::Strategy growthStrategy, int maxBlocksPerChunk, bslma::Allocator *basicAllocator=0)
void release()
Relinquish all memory currently allocated via this pool object.
Definition bdlma_concurrentpool.h:589
bslma::Allocator * allocator() const
Definition bdlma_concurrentpool.h:607
ConcurrentPool(bsls::Types::size_type blockSize, bslma::Allocator *basicAllocator=0)
void reserveCapacity(int numBlocks)
void deallocate(void *address)
ConcurrentPool(bsls::Types::size_type blockSize, bsls::BlockGrowth::Strategy growthStrategy, bslma::Allocator *basicAllocator=0)
void deleteObject(const TYPE *object)
Definition bdlma_concurrentpool.h:576
bsls::Types::size_type blockSize() const
Definition bdlma_concurrentpool.h:599
Definition bdlma_infrequentdeleteblocklist.h:245
bslma::Allocator * allocator() const
Return the allocator used by this object to supply memory.
Definition bdlma_infrequentdeleteblocklist.h:342
Definition bslma_allocator.h:545
Definition bslmt_mutex.h:317
void lock()
Definition bslmt_mutex.h:399
void unlock()
Definition bslmt_mutex.h:417
Definition bsls_atomic.h:1362
#define BSLS_ASSERT_SAFE(X)
Definition bsls_assert.h:1917
#define BSLS_IDENT(str)
BSLS_IDENT() - insert string into .comment binary segment (if supported)
Definition bsls_ident.h:238
Definition bdlma_alignedallocator.h:278
static void deleteObject(const TYPE *object, ALLOCATOR *allocator)
Definition bslma_deleterhelper.h:204
static void deleteObjectRaw(const TYPE *object, ALLOCATOR *allocator)
Definition bslma_deleterhelper.h:225
AlignmentToType< BSLS_MAX_ALIGNMENT >::Type MaxAlignedType
Definition bsls_alignmentutil.h:307
Strategy
Definition bsls_blockgrowth.h:172
std::size_t size_type
Definition bsls_types.h:126