BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bdlma_multipool.h
Go to the documentation of this file.
1/// @file bdlma_multipool.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bdlma_multipool.h -*-C++-*-
8#ifndef INCLUDED_BDLMA_MULTIPOOL
9#define INCLUDED_BDLMA_MULTIPOOL
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bdlma_multipool bdlma_multipool
15/// @brief Provide a memory manager to manage pools of varying block sizes.
16/// @addtogroup bdl
17/// @{
18/// @addtogroup bdlma
19/// @{
20/// @addtogroup bdlma_multipool
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bdlma_multipool-purpose"> Purpose</a>
25/// * <a href="#bdlma_multipool-classes"> Classes </a>
26/// * <a href="#bdlma_multipool-description"> Description </a>
27/// * <a href="#bdlma_multipool-configuration-at-construction"> Configuration at Construction </a>
28/// * <a href="#bdlma_multipool-usage"> Usage </a>
29/// * <a href="#bdlma_multipool-example-1-using-a-bdlma-multipool-directly"> Example 1: Using a bdlma::Multipool Directly </a>
30/// * <a href="#bdlma_multipool-example-2-implementing-an-allocator-using-bdlma-multipool"> Example 2: Implementing an Allocator Using bdlma::Multipool </a>
31///
32/// # Purpose {#bdlma_multipool-purpose}
33/// Provide a memory manager to manage pools of varying block sizes.
34///
35/// # Classes {#bdlma_multipool-classes}
36///
37/// - bdlma::Multipool: memory manager that manages pools of varying block sizes
38///
39/// @see bdlma_pool, bdlma_multipoolallocator
40///
41/// # Description {#bdlma_multipool-description}
42/// This component implements a memory manager, `bdlma::Multipool`,
43/// that maintains a configurable number of `bdlma::Pool` objects, each
44/// dispensing maximally-aligned memory blocks of a unique size. The
45/// `bdlma::Pool` objects are placed in an array, starting at index 0, with each
46/// successive pool managing memory blocks of a size twice that of the previous
47/// pool. Each multipool allocation (deallocation) request allocates memory
48/// from (returns memory to) the internal pool managing memory blocks of the
49/// smallest size not less than the requested size, or else from a separately
50/// managed list of memory blocks, if no internal pool managing memory blocks of
51/// sufficient size exists. Both the `release` method and the destructor of a
52/// `bdlma::Multipool` release all memory currently allocated via the object.
53///
54/// A `bdlma::Multipool` can be depicted visually:
55/// @code
56/// +-----+--- memory blocks of 8 bytes
57/// | |
58/// ======== ----- ----- ------------
59/// |8 bytes |---->| | | ... |
60/// >========< =====^=====^============
61/// |16 bytes|
62/// >========< \___________ __________/
63/// |32 bytes| V
64/// >========< a "chunk"
65/// | |
66/// | ... |
67/// | |
68/// ========
69/// |
70/// +------- array of 'bdlma::Pool'
71/// @endcode
72/// Note that a "chunk" is a large, contiguous block of memory, internal to a
73/// `bdlma::Pool` maintained by the multipool, from which memory blocks of
74/// uniform size are dispensed to users.
75///
76/// ## Configuration at Construction {#bdlma_multipool-configuration-at-construction}
77///
78///
79/// When creating a `bdlma::Multipool`, clients can optionally configure:
80///
81/// 1. NUMBER OF POOLS -- the number of internal pools (the block size managed
82/// by the first pool is eight bytes, with each successive pool managing
83/// blocks of a size twice that of the previous pool).
84/// 2. GROWTH STRATEGY -- geometrically growing chunk size starting from 1 (in
85/// terms of the number of memory blocks per chunk), or fixed chunk size,
86/// specified as either:
87/// - the unique growth strategy for all pools, or
88/// - (if the number of pools is specified) an array of growth strategies
89/// corresponding to each individual pool.
90/// If the growth strategy is not specified, geometric growth is used for all
91/// pools.
92/// 3. MAX BLOCKS PER CHUNK -- the maximum number of memory blocks within a
93/// chunk, specified as either:
94/// - the unique maximum-blocks-per-chunk value for all of the pools, or
95/// - an array of maximum-blocks-per-chunk values corresponding to each
96/// individual pool.
97/// If the maximum blocks per chunk is not specified, an
98/// implementation-defined default value is used. Note that the maximum
99/// blocks per chunk can be configured only if the number of pools is also
100/// configured.
101/// 4. BASIC ALLOCATOR -- the allocator used to supply memory (to replenish an
102/// internal pool, or directly if the maximum block size is exceeded). If
103/// not specified, the currently installed default allocator is used (see
104/// @ref bslma_default ).
105///
106/// A default-constructed multipool has a relatively small,
107/// implementation-defined number of pools, `N`, with respective block sizes
108/// ranging from `2^3 = 8` to `2^(N+2)`. By default, the initial chunk size,
109/// (i.e., the number of blocks of a given size allocated at once to replenish a
110/// pool's memory) is 1, and each pool's chunk size grows geometrically until it
111/// reaches an implementation-defined maximum, at which it is capped. Finally,
112/// unless otherwise specified, all memory comes from the allocator that was the
113/// currently installed default allocator at the time the `bdlma::Multipool` was
114/// created.
115///
116/// Using the various pooling options described above, we can configure the
117/// number of pools maintained, whether replenishment should be adaptive (i.e.,
118/// geometric starting with 1) or fixed at a maximum chunk size, what that
119/// maximum chunk size should be (which need not be an integral power of 2), and
120/// the underlying allocator used to supply memory. Note that both GROWTH
121/// STRATEGY and MAX BLOCKS PER CHUNK can be specified separately either as a
122/// single value applying to all of the maintained pools, or as an array of
123/// values, with the elements applying to each individually maintained pool.
124///
125/// ## Usage {#bdlma_multipool-usage}
126///
127///
128/// This section illustrates intended use of this component.
129///
130/// ### Example 1: Using a bdlma::Multipool Directly {#bdlma_multipool-example-1-using-a-bdlma-multipool-directly}
131///
132///
133/// A `bdlma::Multipool` can be used by containers that hold different types of
134/// elements, each of uniform size, for efficient memory allocation of new
135/// elements. Suppose we have a factory class, `my_MessageFactory`, that
136/// creates messages based on user requests. Each message is created with the
137/// most efficient memory storage possible, using predefined 8-byte, 16-byte,
138/// and 32-byte buffers. If the message size exceeds the three predefined
139/// values, a generic message is used. For efficient memory allocation of
140/// messages, we use a `bdlma::Multipool`.
141///
142/// First, we define our message types as follows:
143/// @code
144/// class my_MessageFactory;
145///
146/// class my_Message {
147/// // This class represents a general message interface that provides a
148/// // 'getMessage' method for clients to retrieve the underlying message.
149///
150/// public:
151/// // CREATORS
152/// virtual ~my_Message() {}
153/// // Destroy this object.
154///
155/// // ACCESSORS
156/// virtual const char *getMessage() = 0;
157/// // Return the null-terminated message string.
158/// };
159///
160/// class my_SmallMessage : public my_Message {
161/// // This class represents an 8-byte message (including null terminator).
162///
163/// // DATA
164/// char d_buffer[8];
165///
166/// // FRIEND
167/// friend class my_MessageFactory;
168///
169/// private:
170/// // NOT IMPLEMENTED
171/// my_SmallMessage(const my_SmallMessage&);
172/// my_SmallMessage& operator=(const my_SmallMessage&);
173///
174/// // PRIVATE CREATORS
175/// my_SmallMessage(const char *msg, int length)
176/// {
177/// assert(length <= 7);
178///
179/// bsl::memcpy(d_buffer, msg, length);
180/// d_buffer[length] = '\0';
181/// }
182///
183/// virtual ~my_SmallMessage() {}
184/// // Destroy this object.
185///
186/// // PRIVATE ACCESSORS
187/// virtual const char *getMessage()
188/// {
189/// return d_buffer;
190/// }
191/// };
192///
193/// class my_MediumMessage : public my_Message {
194/// // This class represents a 16-byte message (including null
195/// // terminator).
196///
197/// // DATA
198/// char d_buffer[16];
199///
200/// // FRIEND
201/// friend class my_MessageFactory;
202///
203/// private:
204/// // NOT IMPLEMENTED
205/// my_MediumMessage(const my_MediumMessage&);
206/// my_MediumMessage& operator=(const my_MediumMessage&);
207///
208/// // PRIVATE CREATORS
209/// my_MediumMessage(const char *msg, int length)
210/// {
211/// assert(length <= 15);
212///
213/// bsl::memcpy(d_buffer, msg, length);
214/// d_buffer[length] = '\0';
215/// }
216///
217/// virtual ~my_MediumMessage() {}
218/// // Destroy this object.
219///
220/// // PRIVATE ACCESSORS
221/// virtual const char *getMessage()
222/// {
223/// return d_buffer;
224/// }
225/// };
226///
227/// class my_LargeMessage : public my_Message {
228/// // This class represents a 32-byte message (including null
229/// // terminator).
230///
231/// // DATA
232/// char d_buffer[32];
233///
234/// // FRIEND
235/// friend class my_MessageFactory;
236///
237/// private:
238/// // NOT IMPLEMENTED
239/// my_LargeMessage(const my_LargeMessage&);
240/// my_LargeMessage& operator=(const my_LargeMessage&);
241///
242/// // PRIVATE CREATORS
243/// my_LargeMessage(const char *msg, int length)
244/// {
245/// assert(length <= 31);
246///
247/// bsl::memcpy(d_buffer, msg, length);
248/// d_buffer[length] = '\0';
249/// }
250///
251/// virtual ~my_LargeMessage() {}
252/// // Destroy this object.
253///
254/// // PRIVATE ACCESSORS
255/// virtual const char *getMessage()
256/// {
257/// return d_buffer;
258/// }
259/// };
260///
261/// class my_GenericMessage : public my_Message {
262/// // This class represents a generic message.
263///
264/// // DATA
265/// char *d_buffer;
266///
267/// // FRIEND
268/// friend class my_MessageFactory;
269///
270/// private:
271/// // NOT IMPLEMENTED
272/// my_GenericMessage(const my_GenericMessage&);
273/// my_GenericMessage& operator=(const my_GenericMessage&);
274///
275/// // PRIVATE CREATORS
276/// my_GenericMessage(char *msg) : d_buffer(msg)
277/// {
278/// }
279///
280/// virtual ~my_GenericMessage() {}
281/// // Destroy this object.
282///
283/// // PRIVATE ACCESSORS
284/// virtual const char *getMessage()
285/// {
286/// return d_buffer;
287/// }
288/// };
289/// @endcode
290/// Then, we define our factory class, `my_MessageFactory`, as follows:
291/// @code
292/// class my_MessageFactory {
293/// // This class implements an efficient message factory that builds and
294/// // returns messages. The life-time of the messages created by this
295/// // factory is the same as this factory.
296///
297/// // DATA
298/// bdlma::Multipool d_multipool; // multipool used to supply memory
299///
300/// private:
301/// // Not implemented:
302/// my_MessageFactory(const my_MessageFactory&);
303///
304/// public:
305/// // CREATORS
306/// my_MessageFactory(bslma::Allocator *basicAllocator = 0);
307/// // Create a message factory. Optionally specify a 'basicAllocator'
308/// // used to supply memory. If 'basicAllocator' is 0, the currently
309/// // installed default allocator is used.
310///
311/// ~my_MessageFactory();
312/// // Destroy this factory and reclaim all messages created by it.
313///
314/// // MANIPULATORS
315/// my_Message *createMessage(const char *data);
316/// // Create a message storing the specified 'data'. The behavior is
317/// // undefined unless 'data' is null-terminated.
318///
319/// void disposeAllMessages();
320/// // Dispose of all created messages.
321///
322/// void disposeMessage(my_Message *message);
323/// // Dispose of the specified 'message'. The behavior is undefined
324/// // unless 'message' was created by this factory, and has not
325/// // already been disposed.
326/// };
327/// @endcode
328/// Next, we define the `inline` methods of `my_MessageFactory`.
329///
330/// In calling the multipool's `release` method, `disposeAllMessages` quickly
331/// deallocates all memory blocks that were used to create messages currently
332/// outstanding from the factory. Following the call to `release`, *all* memory
333/// that had been allocated from the multipool is available for reuse:
334/// @code
335/// // MANIPULATORS
336/// inline
337/// void my_MessageFactory::disposeAllMessages()
338/// {
339/// d_multipool.release();
340/// }
341/// @endcode
342/// Similarly, the call to the multipool's `deleteObject` method in
343/// `disposeMessage` first destroys the message, then releases the memory that
344/// had been allocated for it back to the multipool for use in creating another
345/// message having the same size:
346/// @code
347/// inline
348/// void my_MessageFactory::disposeMessage(my_Message *message)
349/// {
350/// d_multipool.deleteObject(message);
351/// }
352/// @endcode
353/// A multipool optimizes the allocation of memory by using
354/// dynamically-allocated buffers (also known as chunks) to supply memory. As
355/// each chunk can satisfy multiple memory block requests before requiring
356/// additional dynamic memory allocation, the number of dynamic allocation
357/// requests needed is greatly reduced.
358///
359/// For the number of pools managed by the multipool, we chose to use the
360/// implementation-defined default value instead of calculating and specifying a
361/// value. If users instead want to specify the number of pools, the value can
362/// be calculated as the smallest value, `N`, such that the following
363/// relationship holds:
364/// @code
365/// N > log2(sizeof(Object Type)) - 2
366/// @endcode
367/// Next, we define the creators of `my_MessageFactory`:
368/// @code
369/// // CREATORS
370/// my_MessageFactory::my_MessageFactory(bslma::Allocator *basicAllocator)
371/// : d_multipool(basicAllocator)
372/// {
373/// }
374/// @endcode
375/// Note that in the destructor, all outstanding messages are reclaimed
376/// automatically when `d_multipool` is destroyed:
377/// @code
378/// my_MessageFactory::~my_MessageFactory()
379/// {
380/// }
381/// @endcode
382/// Finally, we define the `createMessage` factory method that actually creates
383/// the messages using memory provided by the multipool. A `bdlma::Multipool`
384/// is ideal for allocating the different sized messages since repeated
385/// deallocations might be necessary, which renders a `bdlma::SequentialPool`
386/// unsuitable:
387/// @code
388/// // MANIPULATORS
389/// my_Message *my_MessageFactory::createMessage(const char *data)
390/// {
391/// enum { k_SMALL = 8, k_MEDIUM = 16, k_LARGE = 32 };
392///
393/// const int length = static_cast<int>(bsl::strlen(data));
394///
395/// if (length < k_SMALL) {
396/// return new(d_multipool.allocate(sizeof(my_SmallMessage)))
397/// my_SmallMessage(data, length); // RETURN
398/// }
399///
400/// if (length < k_MEDIUM) {
401/// return new(d_multipool.allocate(sizeof(my_MediumMessage)))
402/// my_MediumMessage(data, length); // RETURN
403/// }
404///
405/// if (length < k_LARGE) {
406/// return new(d_multipool.allocate(sizeof(my_LargeMessage)))
407/// my_LargeMessage(data, length); // RETURN
408/// }
409///
410/// char *buffer = (char *)d_multipool.allocate(length + 1);
411/// bsl::memcpy(buffer, data, length + 1);
412///
413/// return new(d_multipool.allocate(sizeof(my_GenericMessage)))
414/// my_GenericMessage(buffer);
415/// }
416/// @endcode
417///
418/// ### Example 2: Implementing an Allocator Using bdlma::Multipool {#bdlma_multipool-example-2-implementing-an-allocator-using-bdlma-multipool}
419///
420///
421/// Suppose that we want to create a multipool allocator (i.e., that implements
422/// the `bslma::Allocator` interface) that allocates memory from multiple
423/// `bdlma::Pool` objects in a similar fashion to `bdlma::Multipool`. In this
424/// example, we create just such a multipool allocator, `my_MultipoolAllocator`,
425/// that uses a `bdlma::Multipool` to manage the multiple pools.
426///
427/// First, we define the interface of `my_MultipoolAllocator`:
428/// @code
429/// class my_MultipoolAllocator : public bslma::Allocator {
430/// // This class implements the 'bslma::Allocator' protocol to provide an
431/// // allocator that manages a set of memory pools, each dispensing memory
432/// // blocks of a unique size, with each successive pool's block size
433/// // being twice that of the previous one.
434///
435/// // DATA
436/// bdlma::Multipool d_multiPool; // memory manager for allocated memory
437/// // blocks
438///
439/// public:
440/// // CREATORS
441/// my_MultipoolAllocator(bslma::Allocator *basicAllocator = 0);
442/// // Create a multipool allocator. Optionally specify a
443/// // 'basicAllocator' used to supply memory. If 'basicAllocator' is
444/// // 0, the currently installed default allocator is used.
445///
446/// // ...
447///
448/// virtual ~my_MultipoolAllocator();
449/// // Destroy this multipool allocator. All memory allocated from
450/// // this memory pool is released.
451///
452/// // MANIPULATORS
453/// virtual void *allocate(bsls::Types::size_type size);
454/// // Return the address of a contiguous block of maximally-aligned
455/// // memory of (at least) the specified 'size' (in bytes). If 'size'
456/// // is 0, no memory is allocated and 0 is returned.
457///
458/// virtual void deallocate(void *address);
459/// // Relinquish the memory block at the specified 'address' back to
460/// // this multipool allocator for reuse. The behavior is undefined
461/// // unless 'address' is non-zero, was allocated by this multipool
462/// // allocator, and has not already been deallocated.
463/// };
464/// @endcode
465/// Note that the interface and documentation for this class is simplified for
466/// this usage example. Please see @ref bdlma_multipoolallocator for a similar
467/// class meant for production use.
468///
469/// Finally, we provide the trivial implementation of `my_MultipoolAllocator`:
470/// @code
471/// // CREATORS
472/// inline
473/// my_MultipoolAllocator::my_MultipoolAllocator(
474/// bslma::Allocator *basicAllocator)
475/// : d_multiPool(basicAllocator)
476/// {
477/// }
478///
479/// my_MultipoolAllocator::~my_MultipoolAllocator()
480/// {
481/// }
482///
483/// // MANIPULATORS
484/// inline
485/// void *my_MultipoolAllocator::allocate(bsls::Types::size_type size)
486/// {
487/// if (0 == size) {
488/// return 0; // RETURN
489/// }
490///
491/// return d_multiPool.allocate(size);
492/// }
493///
494/// inline
495/// void my_MultipoolAllocator::deallocate(void *address)
496/// {
497/// d_multiPool.deallocate(address);
498/// }
499/// @endcode
500/// @}
501/** @} */
502/** @} */
503
504/** @addtogroup bdl
505 * @{
506 */
507/** @addtogroup bdlma
508 * @{
509 */
510/** @addtogroup bdlma_multipool
511 * @{
512 */
513
514#include <bdlscm_version.h>
515
516#include <bdlma_blocklist.h>
517#include <bdlma_pool.h>
518
519#include <bslma_allocator.h>
520#include <bslma_deleterhelper.h>
521
522#include <bsls_alignmentutil.h>
523#include <bsls_blockgrowth.h>
524#include <bsls_types.h>
525
526
527namespace bdlma {
528
529 // ===============
530 // class Multipool
531 // ===============
532
533/// This class implements a memory manager that maintains a configurable
534/// number of `bdlma::Pool` objects, each dispensing memory blocks of a
535/// unique size. The `bdlma::Pool` objects are placed in an array, with
536/// each successive pool managing memory blocks of size twice that of the
537/// previous pool. Each multipool allocation (deallocation) request
538/// allocates memory from (returns memory to) the internal pool having the
539/// smallest block size not less than the requested size, or, if no pool
540/// manages memory blocks of sufficient size, from a separately managed list
541/// of memory blocks. Both the `release` method and the destructor of a
542/// `bdlma::Multipool` release all memory currently allocated via the
543/// object.
544///
545/// See @ref bdlma_multipool
547
548 // PRIVATE TYPES
549
550 /// This `struct` provides header information for each allocated memory
551 /// block. The header stores the index to the pool used for the memory
552 /// allocation.
553 struct Header {
554
555 union {
556 int d_poolIdx; // index to pool used for this
557 // memory block, or -1 if from
558 // 'd_blockList'
559
561 d_dummy; // force maximum alignment
562 } d_header;
563 };
564
565 // DATA
566 Pool *d_pools_p; // array of memory pools, each
567 // dispensing fixed-size memory
568 // blocks
569
570 int d_numPools; // number of memory pools
571
572 bsls::Types::size_type d_maxBlockSize; // largest memory block size;
573 // dispensed by the
574 // 'd_numPools - 1'th pool; always
575 // a power of 2
576
577 BlockList d_blockList; // memory manager for "large"
578 // memory blocks
579
580 bslma::Allocator *d_allocator_p; // holds (but does not own)
581 // allocator
582
583 private:
584 // PRIVATE MANIPULATORS
585
586 void initialize(bsls::BlockGrowth::Strategy growthStrategy,
587 int maxBlocksPerChunk);
588 void initialize(const bsls::BlockGrowth::Strategy *growthStrategyArray,
589 int maxBlocksPerChunk);
590 void initialize(bsls::BlockGrowth::Strategy growthStrategy,
591 const int *maxBlocksPerChunkArray);
592 /// Initialize this multipool with the specified `growthStrategy[Array]`
593 /// and `maxBlocksPerChunk[Array]`. If an array is used, each
594 /// individual `bdlma::Pool` maintained by this multipool is initialized
595 /// with the corresponding growth strategy or max blocks per chunk entry
596 /// within the array.
597 void initialize(const bsls::BlockGrowth::Strategy *growthStrategyArray,
598 const int *maxBlocksPerChunkArray);
599
600 // PRIVATE ACCESSORS
601
602 /// Return the index of the memory pool in this multipool for an
603 /// allocation request of the specified `size` (in bytes). The behavior
604 /// is undefined unless `size <= maxPooledBlockSize()`. Note that the
605 /// index of the memory pool managing memory blocks having the minimum
606 /// block size is 0.
607 int findPool(bsls::Types::size_type size) const;
608
609 private:
610 // NOT IMPLEMENTED
611 Multipool(const Multipool&);
612 Multipool& operator=(const Multipool&);
613
614 public:
615 // CREATORS
616
617 explicit
618 Multipool(bslma::Allocator *basicAllocator = 0);
619 explicit
620 Multipool(int numPools, bslma::Allocator *basicAllocator = 0);
621 explicit
623 bslma::Allocator *basicAllocator = 0);
625 bsls::BlockGrowth::Strategy growthStrategy,
626 bslma::Allocator *basicAllocator = 0);
627 /// Create a multipool memory manager. Optionally specify `numPools`,
628 /// indicating the number of internally created `bdlma::Pool` objects;
629 /// the block size of the first pool is 8 bytes, with the block size of
630 /// each additional pool successively doubling. If `numPools` is not
631 /// specified, an implementation-defined number of pools `N` -- covering
632 /// memory blocks ranging in size from `2^3 = 8` to `2^(N+2)` -- are
633 /// created. Optionally specify a `growthStrategy` indicating whether
634 /// the number of blocks allocated at once for every internally created
635 /// `bdlma::Pool` should be either fixed or grow geometrically, starting
636 /// with 1. If `growthStrategy` is not specified, the allocation
637 /// strategy for each internally created `bdlma::Pool` object is
638 /// geometric, starting from 1. If `numPools` and `growthStrategy` are
639 /// specified, optionally specify a `maxBlocksPerChunk`, indicating the
640 /// maximum number of blocks to be allocated at once when a pool must be
641 /// replenished. If `maxBlocksPerChunk` is not specified, an
642 /// implementation-defined value is used. Optionally specify a
643 /// `basicAllocator` used to supply memory. If `basicAllocator` is 0,
644 /// the currently installed default allocator is used. Memory
645 /// allocation (and deallocation) requests will be satisfied using the
646 /// internally maintained pool managing memory blocks of the smallest
647 /// size not less than the requested size, or directly from the
648 /// underlying allocator (supplied at construction), if no internal pool
649 /// managing memory blocks of sufficient size exists. The behavior is
650 /// undefined unless `1 <= numPools` and `1 <= maxBlocksPerChunk`. Note
651 /// that, on platforms where
652 /// `8 < bsls::AlignmentUtil::BSLS_MAX_ALIGNMENT`, excess memory may be
653 /// allocated for pools managing smaller blocks. Also note that
654 /// `maxBlocksPerChunk` need not be an integral power of 2; if geometric
655 /// growth would exceed the maximum value, the chunk size is capped at
656 /// that value.
658 bsls::BlockGrowth::Strategy growthStrategy,
659 int maxBlocksPerChunk,
660 bslma::Allocator *basicAllocator = 0);
661
663 const bsls::BlockGrowth::Strategy *growthStrategyArray,
664 bslma::Allocator *basicAllocator = 0);
666 const bsls::BlockGrowth::Strategy *growthStrategyArray,
667 int maxBlocksPerChunk,
668 bslma::Allocator *basicAllocator = 0);
670 bsls::BlockGrowth::Strategy growthStrategy,
671 const int *maxBlocksPerChunkArray,
672 bslma::Allocator *basicAllocator = 0);
673 /// Create a multipool memory manager having the specified `numPools`,
674 /// indicating the number of internally created `bdlma::Pool` objects;
675 /// the block size of the first pool is 8 bytes, with the block size of
676 /// each additional pool successively doubling. Optionally specify a
677 /// `growthStrategy` indicating whether the number of blocks allocated
678 /// at once for every internally created `bdlma::Pool` should be either
679 /// fixed or grow geometrically, starting with 1. If `growthStrategy`
680 /// is not specified, optionally specify a `growthStrategyArray`,
681 /// indicating the strategies for each individual `bdlma::Pool` created
682 /// by this object. If neither `growthStrategy` nor
683 /// `growthStrategyArray` is specified, the allocation strategy for each
684 /// internally created `bdlma::Pool` object will grow geometrically,
685 /// starting from 1. Optionally specify a `maxBlocksPerChunk`,
686 /// indicating the maximum number of blocks to be allocated at once when
687 /// a pool must be replenished. If `maxBlocksPerChunk` is not
688 /// specified, optionally specify a `maxBlocksPerChunkArray`, indicating
689 /// the maximum number of blocks to allocate at once for each
690 /// individually created `bdlma::Pool` object. If neither
691 /// `maxBlocksPerChunk` nor `maxBlocksPerChunkArray` is specified, an
692 /// implementation-defined value is used. Optionally specify a
693 /// `basicAllocator` used to supply memory. If `basicAllocator` is 0,
694 /// the currently installed default allocator is used. Memory
695 /// allocation (and deallocation) requests will be satisfied using the
696 /// internally maintained pool managing memory blocks of the smallest
697 /// size not less than the requested size, or directly from the
698 /// underlying allocator (supplied at construction), if no internal pool
699 /// managing memory blocks of sufficient size exists. The behavior is
700 /// undefined unless `1 <= numPools`, `growthStrategyArray` has at least
701 /// `numPools` strategies, `1 <= maxBlocksPerChunk`, and
702 /// `maxBlocksPerChunkArray` has at least `numPools` positive values.
703 /// Note that, on platforms where
704 /// `8 < bsls::AlignmentUtil::BSLS_MAX_ALIGNMENT`, excess memory may be
705 /// allocated for pools managing smaller blocks. Also note that the
706 /// maximum need not be an integral power of 2; if geometric growth
707 /// would exceed a maximum value, the chunk size is capped at that
708 /// value.
710 const bsls::BlockGrowth::Strategy *growthStrategyArray,
711 const int *maxBlocksPerChunkArray,
712 bslma::Allocator *basicAllocator = 0);
713
714 /// Destroy this multipool. All memory allocated from this memory pool
715 /// is released.
717
718 // MANIPULATORS
719
720 /// Return the address of a contiguous block of maximally-aligned memory
721 /// of (at least) the specified `size` (in bytes). If `size` is 0, no
722 /// memory is allocated and 0 is returned. If
723 /// `size > maxPooledBlockSize()`, the memory allocation is managed
724 /// directly by the underlying allocator, and will not be pooled, but
725 /// will be deallocated when the `release` method is called, or when
726 /// this object is destroyed.
728
729 /// Relinquish the memory block at the specified `address` back to this
730 /// multipool object for reuse. The behavior is undefined unless
731 /// `address` is non-zero, was allocated by this multipool object, and
732 /// has not already been deallocated.
733 void deallocate(void *address);
734
735 /// Destroy the specified `object` based on its dynamic type and then
736 /// use this multipool object to deallocate its memory footprint. This
737 /// method has no effect if `object` is 0. The behavior is undefined
738 /// unless `object`, when cast appropriately to `void *`, was allocated
739 /// using this multipool object and has not already been deallocated.
740 /// Note that `dynamic_cast<void *>(object)` is applied if `TYPE` is
741 /// polymorphic, and `static_cast<void *>(object)` is applied otherwise.
742 template <class TYPE>
743 void deleteObject(const TYPE *object);
744
745 /// Destroy the specified `object` and then use this multipool to
746 /// deallocate its memory footprint. This method has no effect if
747 /// `object` is 0. The behavior is undefined unless `object` is **not** a
748 /// secondary base class pointer (i.e., the address is (numerically) the
749 /// same as when it was originally dispensed by this multipool), was
750 /// allocated using this multipool, and has not already been
751 /// deallocated.
752 template <class TYPE>
753 void deleteObjectRaw(const TYPE *object);
754
755 /// Relinquish all memory currently allocated via this multipool object.
756 void release();
757
758 /// Reserve memory from this multipool to satisfy memory requests for at
759 /// least the specified `numBlocks` having the specified `size` (in
760 /// bytes) before the pool replenishes. If `size` is 0, this method has
761 /// no effect. The behavior is undefined unless
762 /// `size <= maxPooledBlockSize()` and `0 <= numBlocks`.
763 void reserveCapacity(bsls::Types::size_type size, int numBlocks);
764
765 // ACCESSORS
766
767 /// Return the number of pools managed by this multipool object.
768 int numPools() const;
769
770 /// Return the maximum size of memory blocks that are pooled by this
771 /// multipool object. Note that the maximum value is defined as:
772 /// @code
773 /// 2 ^ (numPools + 2)
774 /// @endcode
775 /// where `numPools` is either specified at construction, or an
776 /// implementation-defined value.
778
779 // Aspects
780
781 /// Return the allocator used by this object to allocate memory. Note
782 /// that this allocator can not be used to deallocate memory
783 /// allocated through this pool.
785};
786
787// ============================================================================
788// INLINE DEFINITIONS
789// ============================================================================
790
791 // ---------------
792 // class Multipool
793 // ---------------
794
795// MANIPULATORS
796template <class TYPE>
797inline
798void Multipool::deleteObject(const TYPE *object)
799{
801}
802
803template <class TYPE>
804inline
805void Multipool::deleteObjectRaw(const TYPE *object)
806{
808}
809
810// ACCESSORS
811inline
813{
814 return d_numPools;
815}
816
817inline
819{
820 return d_maxBlockSize;
821}
822
823// Aspects
824
825inline
827{
828 return d_allocator_p;
829}
830
831} // close package namespace
832
833
834#endif
835
836// ----------------------------------------------------------------------------
837// Copyright 2016 Bloomberg Finance L.P.
838//
839// Licensed under the Apache License, Version 2.0 (the "License");
840// you may not use this file except in compliance with the License.
841// You may obtain a copy of the License at
842//
843// http://www.apache.org/licenses/LICENSE-2.0
844//
845// Unless required by applicable law or agreed to in writing, software
846// distributed under the License is distributed on an "AS IS" BASIS,
847// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
848// See the License for the specific language governing permissions and
849// limitations under the License.
850// ----------------------------- END-OF-FILE ----------------------------------
851
852/** @} */
853/** @} */
854/** @} */
Definition bdlma_blocklist.h:235
Definition bdlma_multipool.h:546
void deleteObject(const TYPE *object)
Definition bdlma_multipool.h:798
Multipool(int numPools, bsls::BlockGrowth::Strategy growthStrategy, bslma::Allocator *basicAllocator=0)
void release()
Relinquish all memory currently allocated via this multipool object.
Multipool(bsls::BlockGrowth::Strategy growthStrategy, bslma::Allocator *basicAllocator=0)
bslma::Allocator * allocator() const
Definition bdlma_multipool.h:826
int numPools() const
Return the number of pools managed by this multipool object.
Definition bdlma_multipool.h:812
void deallocate(void *address)
Multipool(int numPools, bslma::Allocator *basicAllocator=0)
Multipool(int numPools, const bsls::BlockGrowth::Strategy *growthStrategyArray, const int *maxBlocksPerChunkArray, bslma::Allocator *basicAllocator=0)
Multipool(bslma::Allocator *basicAllocator=0)
Multipool(int numPools, const bsls::BlockGrowth::Strategy *growthStrategyArray, bslma::Allocator *basicAllocator=0)
Multipool(int numPools, const bsls::BlockGrowth::Strategy *growthStrategyArray, int maxBlocksPerChunk, bslma::Allocator *basicAllocator=0)
Multipool(int numPools, bsls::BlockGrowth::Strategy growthStrategy, int maxBlocksPerChunk, bslma::Allocator *basicAllocator=0)
void reserveCapacity(bsls::Types::size_type size, int numBlocks)
bsls::Types::size_type maxPooledBlockSize() const
Definition bdlma_multipool.h:818
void deleteObjectRaw(const TYPE *object)
Definition bdlma_multipool.h:805
void * allocate(bsls::Types::size_type size)
Multipool(int numPools, bsls::BlockGrowth::Strategy growthStrategy, const int *maxBlocksPerChunkArray, bslma::Allocator *basicAllocator=0)
Definition bdlma_pool.h:335
Definition bslma_allocator.h:457
#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