BDE 4.14.0 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
338 /// linked list of free memory blocks. Note that this type is
339 /// replicated in `bdlma_concurrentpool.cpp` to provide access to a
340 /// compatible type from static methods defined in `bdema_pool.cpp`.
341 struct Link {
342
343 union {
344 bsls::AtomicOperations::AtomicTypes::Int d_refCount;
346 };
347 Link *volatile d_next_p; // pointer to next link
348 };
349
350 // DATA
351 bsls::Types::size_type d_blockSize; // size of each allocated memory block
352 // returned to client
353
354 bsls::Types::size_type d_internalBlockSize;
355 // actual size of each block
356 // maintained on free list (contains
357 // overhead for 'Link')
358
359 int d_chunkSize; // current chunk size (in
360 // blocks-per-chunk)
361
362 int d_maxBlocksPerChunk;
363 // maximum chunk size (in
364 // blocks-per-chunk)
365
366 bsls::BlockGrowth::Strategy d_growthStrategy;
367 // growth strategy of the chunk size
368
369 bsls::AtomicPointer<Link> d_freeList;
370 // linked list of free memory blocks
371
373 // memory manager for allocated memory
374
375 bslmt::Mutex d_mutex; // protects access to the block list
376
377 // PRIVATE MANIPULATORS
378
379 /// Dynamically allocate a new chunk using the pool's underlying growth
380 /// strategy, and use the chunk to replenish the free memory list of
381 /// this pool. The behavior is undefined unless the calling thread has
382 /// a lock on `d_mutex`.
383 void replenish();
384
385 private:
386 // NOT IMPLEMENTED
388 ConcurrentPool& operator=(const ConcurrentPool&);
389
390 public:
391 // CREATORS
392
394 bslma::Allocator *basicAllocator = 0);
396 bsls::BlockGrowth::Strategy growthStrategy,
397 bslma::Allocator *basicAllocator = 0);
398 /// Create a memory pool that returns blocks of contiguous memory of the
399 /// specified `blockSize` (in bytes) for each `allocate` method
400 /// invocation. Optionally specify a `growthStrategy` used to control
401 /// the growth of internal memory chunks (from which memory blocks are
402 /// dispensed). If `growthStrategy` is not specified, geometric growth
403 /// is used. Optionally specify `maxBlocksPerChunk` as the maximum
404 /// chunk size. If geometric growth is used, the chunk size grows
405 /// starting at `blockSize`, doubling in size until the size is exactly
406 /// `blockSize * maxBlocksPerChunk`. If constant growth is used, the
407 /// chunk size is always `maxBlocksPerChunk`. If `maxBlocksPerChunk` is
408 /// not specified, an implementation-defined value is used. Optionally
409 /// specify a `basicAllocator` used to supply memory. If
410 /// `basicAllocator` is 0, the currently installed default allocator is
411 /// used. The behavior is undefined unless `1 <= blockSize` and
412 /// `1 <= maxBlocksPerChunk`.
414 bsls::BlockGrowth::Strategy growthStrategy,
415 int maxBlocksPerChunk,
416 bslma::Allocator *basicAllocator = 0);
417
418 /// Destroy this pool, releasing all associated memory back to the
419 /// underlying allocator.
421
422 // MANIPULATORS
423
424 /// Return the address of a contiguous block of memory having the fixed
425 /// block size specified at construction.
426 void *allocate();
427
428 /// Relinquish the memory block at the specified `address` back to this
429 /// pool object for reuse. The behavior is undefined unless `address`
430 /// is non-zero, was allocated by this pool, and has not already been
431 /// deallocated.
432 void deallocate(void *address);
433
434 /// Destroy the specified `object` based on its dynamic type and then
435 /// use this pool to deallocate its memory footprint. This method has
436 /// no effect if `object` is 0. The behavior is undefined unless
437 /// `object`, when cast appropriately to `void *`, was allocated using
438 /// this pool and has not already been deallocated. Note that
439 /// `dynamic_cast<void *>(object)` is applied if `TYPE` is polymorphic,
440 /// and `static_cast<void *>(object)` is applied otherwise.
441 template <class TYPE>
442 void deleteObject(const TYPE *object);
443
444 /// Destroy the specified `object` and then use this pool to deallocate
445 /// its memory footprint. This method has no effect if `object` is 0.
446 /// The behavior is undefined unless `object` is **not** a secondary base
447 /// class pointer (i.e., the address is (numerically) the same as when
448 /// it was originally dispensed by this pool), was allocated using this
449 /// pool, and has not already been deallocated.
450 template <class TYPE>
451 void deleteObjectRaw(const TYPE *object);
452
453 /// Relinquish all memory currently allocated via this pool object.
454 void release();
455
456 /// Reserve memory from this pool to satisfy memory requests for at
457 /// least the specified `numBlocks` before the pool replenishes. The
458 /// behavior is undefined unless `0 <= numBlocks`.
459 void reserveCapacity(int numBlocks);
460
461 // ACCESSORS
462
463 /// Return the size (in bytes) of the memory blocks allocated from this
464 /// pool object. Note that all blocks dispensed by this pool have the
465 /// same size.
467
468 // Aspects
469
470 /// Return the allocator used by this object to allocate memory. Note
471 /// that this allocator can not be used to deallocate memory
472 /// allocated through this pool.
474};
475
476} // close package namespace
477
478
479// Note that the 'new' and 'delete' operators are declared outside the
480// 'BloombergLP' namespace so that they do not hide the standard placement
481// 'new' and 'delete' operators (i.e.,
482// 'void *operator new(bsl::size_t, void *)' and
483// 'void operator delete(void *)').
484//
485// Also note that only the scalar versions of operators 'new' and 'delete' are
486// provided, because overloading 'new' (and 'delete') with their array versions
487// would cause dangerous ambiguity. Consider what would have happened had we
488// overloaded the array version of 'operator new':
489//..
490// void *operator new[](bsl::size_t size, BloombergLP::bdlma::Pool& pool);
491//..
492// A user of 'bdlma::Pool' may expect to be able to use array 'operator new' as
493// follows:
494//..
495// new (*pool) my_Type[...];
496//..
497// The problem is that this expression returns an array that cannot be safely
498// deallocated. On the one hand, there is no syntax in C++ to invoke an
499// overloaded 'operator delete'; on the other hand, the pointer returned by
500// 'operator new' cannot be passed to the 'deallocate' method directly because
501// the pointer is different from the one returned by the 'allocate' method.
502// The compiler offsets the value of this pointer by a header, which is used to
503// maintain the number of objects in the array (so that 'operator delete' can
504// destroy the right number of objects).
505
506// FREE OPERATORS
507
508/// Return a block of memory of the specified `size` (in bytes) allocated
509/// from the specified `pool`. The behavior is undefined unless `size` is
510/// the same or smaller than the `blockSize` with which `pool` was
511/// constructed. Note that an object may allocate additional memory
512void *operator new(bsl::size_t size, BloombergLP::bdlma::ConcurrentPool& pool);
513
514 // internally, requiring the allocator to be passed in as a constructor
515 // argument:
516 //..
517 // my_Type *newMyType(bdlma::ConcurrentPool *pool,
518 // bslma::Allocator *basicAllocator)
519 // {
520 // return new (*pool) my_Type(..., basicAllocator);
521 // }
522 //..
523 // Also note that the analogous version of 'operator delete' should not be
524 // called directly. Instead, this component provides a static template
525 // member function, 'deleteObject', parameterized by 'TYPE':
526 //..
527 // void deleteMyType(my_Type *t, bdlma::ConcurrentPool *pool)
528 // {
529 // pool->deleteObject(t);
530 // }
531 //..
532 // 'deleteObject' performs the following:
533 //..
534 // t->~my_Type();
535 // pool->deallocate(t);
536 //..
537
538/// Use the specified `pool` to deallocate the memory at the specified
539/// `address`. The behavior is undefined unless `address` was allocated
540/// using `pool` and has not already been deallocated. This operator is
541/// supplied solely to allow the compiler to arrange for it to be called in
542/// case of an exception. Client code should not call it; use
543/// `bdlma::ConcurrentPool::deleteObject()` instead.
544inline
545void operator delete(void *address, BloombergLP::bdlma::ConcurrentPool& pool);
546
547// ============================================================================
548// INLINE DEFINITIONS
549// ============================================================================
550
551
552namespace bdlma {
553
554 // --------------------
555 // class ConcurrentPool
556 // --------------------
557
558// MANIPULATORS
559template<class TYPE>
560inline
561void ConcurrentPool::deleteObject(const TYPE *object)
562{
564}
565
566template<class TYPE>
567inline
568void ConcurrentPool::deleteObjectRaw(const TYPE *object)
569{
571}
572
573inline
575{
576 d_mutex.lock();
577 d_freeList = (Link*)0;
578 d_blockList.release();
579 d_mutex.unlock();
580}
581
582// ACCESSORS
583inline
585{
586 return d_blockSize;
587}
588
589// Aspects
590
591inline
593{
594 return d_blockList.allocator();
595}
596
597} // close package namespace
598
599
600// FREE OPERATORS
601inline
602void *operator new(bsl::size_t size, BloombergLP::bdlma::ConcurrentPool& pool)
603{
604#if defined(BSLS_ASSERT_SAFE_IS_USED)
605 // gcc-4.8.1 introduced a new warning for unused typedefs, so this typedef
606 // should only be present in SAFE mode builds (where it is used).
607
608 typedef BloombergLP::bsls::AlignmentUtil Util;
609
610 BSLS_ASSERT_SAFE(size <= pool.blockSize()
611 && Util::calculateAlignmentFromSize(size)
612 <= Util::calculateAlignmentFromSize(pool.blockSize()));
613#endif
614
615 static_cast<void>(size); // suppress "unused parameter" warnings
616 return pool.allocate();
617}
618
619inline
620void operator delete(void *address, BloombergLP::bdlma::ConcurrentPool& pool)
621{
622 pool.deallocate(address);
623}
624
625#endif
626
627// ----------------------------------------------------------------------------
628// Copyright 2016 Bloomberg Finance L.P.
629//
630// Licensed under the Apache License, Version 2.0 (the "License");
631// you may not use this file except in compliance with the License.
632// You may obtain a copy of the License at
633//
634// http://www.apache.org/licenses/LICENSE-2.0
635//
636// Unless required by applicable law or agreed to in writing, software
637// distributed under the License is distributed on an "AS IS" BASIS,
638// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
639// See the License for the specific language governing permissions and
640// limitations under the License.
641// ----------------------------- END-OF-FILE ----------------------------------
642
643/** @} */
644/** @} */
645/** @} */
Definition bdlma_concurrentpool.h:332
void deleteObjectRaw(const TYPE *object)
Definition bdlma_concurrentpool.h:568
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:574
bslma::Allocator * allocator() const
Definition bdlma_concurrentpool.h:592
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:561
bsls::Types::size_type blockSize() const
Definition bdlma_concurrentpool.h:584
Definition bdlma_infrequentdeleteblocklist.h:241
bslma::Allocator * allocator() const
Return the allocator used by this object to supply memory.
Definition bdlma_infrequentdeleteblocklist.h:335
Definition bslma_allocator.h:457
Definition bslmt_mutex.h:315
void lock()
Definition bslmt_mutex.h:392
void unlock()
Definition bslmt_mutex.h:410
Definition bsls_atomic.h:1349
#define BSLS_ASSERT_SAFE(X)
Definition bsls_assert.h:1762
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
Definition bdlma_alignedallocator.h:276
static void deleteObject(const TYPE *object, ALLOCATOR *allocator)
Definition bslma_deleterhelper.h:196
static void deleteObjectRaw(const TYPE *object, ALLOCATOR *allocator)
Definition bslma_deleterhelper.h:217
AlignmentToType< BSLS_MAX_ALIGNMENT >::Type MaxAlignedType
Definition bsls_alignmentutil.h:282
Strategy
Definition bsls_blockgrowth.h:169
std::size_t size_type
Definition bsls_types.h:124