BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bdlma_sequentialpool.h
Go to the documentation of this file.
1/// @file bdlma_sequentialpool.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bdlma_sequentialpool.h -*-C++-*-
8#ifndef INCLUDED_BDLMA_SEQUENTIALPOOL
9#define INCLUDED_BDLMA_SEQUENTIALPOOL
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bdlma_sequentialpool bdlma_sequentialpool
15/// @brief Provide sequential memory using dynamically-allocated buffers.
16/// @addtogroup bdl
17/// @{
18/// @addtogroup bdlma
19/// @{
20/// @addtogroup bdlma_sequentialpool
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bdlma_sequentialpool-purpose"> Purpose</a>
25/// * <a href="#bdlma_sequentialpool-classes"> Classes </a>
26/// * <a href="#bdlma_sequentialpool-description"> Description </a>
27/// * <a href="#bdlma_sequentialpool-optional-initialsize-parameter"> Optional initialSize Parameter </a>
28/// * <a href="#bdlma_sequentialpool-optional-maxbuffersize-parameter"> Optional maxBufferSize Parameter </a>
29/// * <a href="#bdlma_sequentialpool-optional-growthstrategy-parameter"> Optional growthStrategy Parameter </a>
30/// * <a href="#bdlma_sequentialpool-optional-alignmentstrategy-parameter"> Optional alignmentStrategy Parameter </a>
31/// * <a href="#bdlma_sequentialpool-usage"> Usage </a>
32/// * <a href="#bdlma_sequentialpool-example-1-using-bdlma-sequentialpool-for-efficient-allocations"> Example 1: Using bdlma::SequentialPool for Efficient Allocations </a>
33/// * <a href="#bdlma_sequentialpool-example-2-implementing-an-allocator-using-bdlma-sequentialpool"> Example 2: Implementing an Allocator Using bdlma::SequentialPool </a>
34///
35/// # Purpose {#bdlma_sequentialpool-purpose}
36/// Provide sequential memory using dynamically-allocated buffers.
37///
38/// # Classes {#bdlma_sequentialpool-classes}
39///
40/// - bdlma::SequentialPool: memory pool using dynamically-allocated buffers
41///
42/// @see bdlma_infrequentdeleteblocklist, bdlma_sequentialallocator
43///
44/// # Description {#bdlma_sequentialpool-description}
45/// This component provides a fast sequential memory pool,
46/// `bdlma::SequentialPool`, that dispenses heterogeneous memory blocks (of
47/// varying, user-specified sizes) from a dynamically-allocated internal buffer.
48/// If an allocation request exceeds the remaining free memory space in the
49/// internal buffer, the pool either replenishes its buffer with new memory to
50/// satisfy the request, or returns a separate memory block, depending on
51/// whether the request size exceeds an optionally-specified maximum buffer
52/// size. The `release` method releases all memory allocated through the pool,
53/// as does the destructor. The `rewind` method releases all memory allocated
54/// through the pool and returns to the underlying allocator *only* memory that
55/// was allocated outside of the typical internal buffer growth of the pool
56/// (i.e., large blocks). Note that individually allocated memory blocks cannot
57/// be separately deallocated.
58///
59/// A `bdlma::SequentialPool` is typically used when fast allocation and
60/// deallocation is needed, but the user does not know in advance the maximum
61/// amount of memory needed.
62///
63/// ## Optional initialSize Parameter {#bdlma_sequentialpool-optional-initialsize-parameter}
64///
65///
66/// An optional `initialSize` parameter can be supplied at construction to
67/// specify the initial size of the internal buffer. If `initialSize` is not
68/// supplied, an implementation-defined value is used for the initial internal
69/// size of the buffer.
70///
71/// ### Optional maxBufferSize Parameter {#bdlma_sequentialpool-optional-maxbuffersize-parameter}
72///
73///
74/// If `initialSize` is specified, an optional `maxBufferSize` parameter can be
75/// supplied at construction to specify the maximum buffer size for geometric
76/// growth. Once the internal buffer grows up to the `maxBufferSize`, further
77/// requests that exceed this size will be served by a separate memory block
78/// instead of the internal buffer. The behavior is undefined unless
79/// `maxBufferSize >= initialSize`. Note that `reserveCapacity` always ensures
80/// that the requested number of bytes is available (allocating a new internal
81/// buffer if necessary) regardless of whether the size of the request exceeds
82/// `maxBufferSize`.
83///
84/// ## Optional growthStrategy Parameter {#bdlma_sequentialpool-optional-growthstrategy-parameter}
85///
86///
87/// An optional `growthStrategy` parameter can be supplied at construction to
88/// specify the growth rate of the dynamically-allocated buffers. The buffers
89/// can grow either geometrically or remain constant in size. If
90/// `growthStrategy` is not specified, geometric growth is used. See
91/// @ref bsls_blockgrowth for more details.
92///
93/// ## Optional alignmentStrategy Parameter {#bdlma_sequentialpool-optional-alignmentstrategy-parameter}
94///
95///
96/// An optional `alignmentStrategy` parameter can be supplied at construction to
97/// specify the memory alignment strategy. Allocated memory blocks can either
98/// follow maximum alignment, natural alignment, or 1-byte alignment. If
99/// `alignmentStrategy` is not specified, natural alignment is used. See
100/// @ref bsls_alignment for more details.
101///
102/// ## Usage {#bdlma_sequentialpool-usage}
103///
104///
105/// This section illustrates intended use of this component.
106///
107/// ### Example 1: Using bdlma::SequentialPool for Efficient Allocations {#bdlma_sequentialpool-example-1-using-bdlma-sequentialpool-for-efficient-allocations}
108///
109///
110/// Suppose we define a container class, `my_IntDoubleArray`, that holds both
111/// `int` and `double` values. The class can be implemented using two parallel
112/// arrays: one storing the type information, and the other storing pointers to
113/// the `int` and `double` values. For efficient memory allocation, we can use
114/// a `bdlma::SequentialPool` for memory allocation:
115/// @code
116/// // my_intdoublearray.h
117///
118/// class my_IntDoubleArray {
119/// // This class implements an efficient container for an array that
120/// // stores both 'int' and 'double' values.
121///
122/// // DATA
123/// char *d_typeArray_p; // array indicating the type of corresponding
124/// // values stored in 'd_valueArray_p'
125///
126/// void **d_valueArray_p; // array of pointers to the values stored
127///
128/// int d_length; // number of values stored
129///
130/// int d_capacity; // physical capacity of the type and value
131/// // arrays
132///
133/// bdlma::SequentialPool
134/// d_pool; // sequential memory pool used to supply memory
135///
136/// private:
137/// // PRIVATE MANIPULATORS
138/// void increaseSize();
139/// // Increase the capacity of the internal arrays used to store
140/// // elements added to this array by at least one element.
141///
142/// // Not implemented:
143/// my_IntDoubleArray(const my_IntDoubleArray&);
144///
145/// public:
146/// // TYPES
147/// enum Type { k_MY_INT, k_MY_DOUBLE };
148///
149/// // CREATORS
150/// explicit my_IntDoubleArray(bslma::Allocator *basicAllocator = 0);
151/// // Create an 'int'-'double' array. Optionally specify a
152/// // 'basicAllocator' used to supply memory. If 'basicAllocator' is
153/// // 0, the currently installed default allocator is used.
154///
155/// ~my_IntDoubleArray();
156/// // Destroy this array and all elements held by it.
157///
158/// // ...
159///
160/// // MANIPULATORS
161/// void appendInt(int value);
162/// // Append the specified 'int' 'value' to this array.
163///
164/// void appendDouble(double value);
165/// // Append the specified 'double' 'value' to this array.
166///
167/// void removeAll();
168/// // Remove all elements from this array.
169///
170/// // ...
171/// };
172/// @endcode
173/// The use of a sequential pool and the `release` method allows the `removeAll`
174/// method to quickly deallocate memory of all elements:
175/// @code
176/// // MANIPULATORS
177/// inline
178/// void my_IntDoubleArray::removeAll()
179/// {
180/// d_pool.release();
181/// d_length = 0;
182/// }
183/// @endcode
184/// The sequential pool optimizes the allocation of memory by using
185/// dynamically-allocated buffers to supply memory. This greatly reduces the
186/// amount of dynamic allocation needed:
187/// @code
188/// // my_intdoublearray.cpp
189///
190/// enum { k_INITIAL_SIZE = 1 };
191///
192/// // PRIVATE MANIPULATORS
193/// void my_IntDoubleArray::increaseSize()
194/// {
195/// // Implementation elided.
196/// // ...
197/// }
198///
199/// // CREATORS
200/// my_IntDoubleArray::my_IntDoubleArray(bslma::Allocator *basicAllocator)
201/// : d_length(0)
202/// , d_capacity(k_INITIAL_SIZE)
203/// , d_pool(basicAllocator)
204/// {
205/// d_typeArray_p = static_cast<char *>(
206/// d_pool.allocate(d_capacity * sizeof *d_typeArray_p));
207/// d_valueArray_p = static_cast<void **>(
208/// d_pool.allocate(d_capacity * sizeof *d_valueArray_p));
209/// }
210/// @endcode
211/// Note that in the destructor, all outstanding memory blocks are deallocated
212/// automatically when `d_pool` is destroyed:
213/// @code
214/// my_IntDoubleArray::~my_IntDoubleArray()
215/// {
216/// assert(0 <= d_length);
217/// assert(0 <= d_capacity);
218/// assert(d_length <= d_capacity);
219/// }
220///
221/// // MANIPULATORS
222/// void my_IntDoubleArray::appendInt(int value)
223/// {
224/// if (d_length >= d_capacity) {
225/// increaseSize();
226/// }
227///
228/// int *item = static_cast<int *>(d_pool.allocate(sizeof *item));
229/// *item = value;
230///
231/// d_typeArray_p[d_length] = static_cast<char>(k_MY_INT);
232/// d_valueArray_p[d_length] = item;
233///
234/// ++d_length;
235/// }
236///
237/// void my_IntDoubleArray::appendDouble(double value)
238/// {
239/// if (d_length >= d_capacity) {
240/// increaseSize();
241/// }
242///
243/// double *item = static_cast<double *>(d_pool.allocate(sizeof *item));
244/// *item = value;
245///
246/// d_typeArray_p[d_length] = static_cast<char>(k_MY_DOUBLE);
247/// d_valueArray_p[d_length] = item;
248///
249/// ++d_length;
250/// }
251/// @endcode
252///
253/// ### Example 2: Implementing an Allocator Using bdlma::SequentialPool {#bdlma_sequentialpool-example-2-implementing-an-allocator-using-bdlma-sequentialpool}
254///
255///
256/// `bslma::Allocator` is used throughout the interfaces of BDE components.
257/// Suppose we would like to create a fast allocator, `my_FastAllocator`, that
258/// allocates memory from a buffer in a similar fashion to
259/// `bdlma::SequentialPool`. `bdlma::SequentialPool` can be used directly to
260/// implement such an allocator.
261///
262/// Note that the documentation for this class is simplified for this usage
263/// example. Please see @ref bdlma_sequentialallocator for full documentation of a
264/// similar class.
265/// @code
266/// class my_SequentialAllocator : public bslma::Allocator {
267/// // This class implements the 'bslma::Allocator' protocol to provide a
268/// // fast allocator of heterogeneous blocks of memory (of varying,
269/// // user-specified sizes) from dynamically-allocated internal buffers.
270///
271/// // DATA
272/// bdlma::SequentialPool d_pool; // memory manager for allocated memory
273/// // blocks
274///
275/// public:
276/// // CREATORS
277/// explicit my_SequentialAllocator(bslma::Allocator *basicAllocator = 0);
278/// // Create an allocator for allocating memory blocks from
279/// // dynamically-allocated internal buffers. Optionally specify a
280/// // 'basicAllocator' used to supply memory. If 'basicAllocator' is
281/// // 0, the currently installed default allocator is used.
282///
283/// ~my_SequentialAllocator();
284/// // Destroy this allocator. All memory allocated from this
285/// // allocator is released.
286///
287/// // MANIPULATORS
288/// virtual void *allocate(size_type size);
289/// // Return the address of a contiguous block of memory of the
290/// // specified 'size' (in bytes).
291///
292/// virtual void deallocate(void *address);
293/// // This method has no effect on the memory block at the specified
294/// // 'address' as all memory allocated by this allocator is managed.
295/// // The behavior is undefined unless 'address' was allocated by this
296/// // allocator, and has not already been deallocated.
297/// };
298///
299/// // CREATORS
300/// inline
301/// my_SequentialAllocator::my_SequentialAllocator(
302/// bslma::Allocator *basicAllocator)
303/// : d_pool(basicAllocator)
304/// {
305/// }
306///
307/// inline
308/// my_SequentialAllocator::~my_SequentialAllocator()
309/// {
310/// d_pool.release();
311/// }
312///
313/// // MANIPULATORS
314/// inline
315/// void *my_SequentialAllocator::allocate(size_type size)
316/// {
317/// return d_pool.allocate(size);
318/// }
319///
320/// inline
321/// void my_SequentialAllocator::deallocate(void *)
322/// {
323/// }
324/// @endcode
325/// @}
326/** @} */
327/** @} */
328
329/** @addtogroup bdl
330 * @{
331 */
332/** @addtogroup bdlma
333 * @{
334 */
335/** @addtogroup bdlma_sequentialpool
336 * @{
337 */
338
339#include <bdlscm_version.h>
340
341#include <bdlma_buffermanager.h>
343
344#include <bslma_allocator.h>
345
346#include <bsls_alignment.h>
347#include <bsls_alignmentutil.h>
348#include <bsls_assert.h>
349#include <bsls_blockgrowth.h>
350#include <bsls_objectbuffer.h>
351#include <bsls_performancehint.h>
352#include <bsls_platform.h>
353#include <bsls_review.h>
354#include <bsls_types.h>
355
356#include <bsl_cstddef.h>
357#include <bsl_cstdint.h>
358
359
360namespace bdlma {
361
362 // ====================
363 // class SequentialPool
364 // ====================
365
366/// This class implements a fast memory pool that efficiently dispenses
367/// heterogeneous blocks of memory (of varying, user-specified sizes) from a
368/// sequence of dynamically-allocated internal buffers. Memory for the
369/// internal buffers is supplied by an (optional) allocator supplied at
370/// construction; if no allocator is supplied, the currently installed
371/// default allocator is used. If an allocation exceeds the remaining free
372/// memory space in the current buffer, the pool replenishes its internal
373/// buffer with new memory to satisfy the request. This class is
374/// *exception* *neutral*: If memory cannot be allocated, the behavior is
375/// defined by the (optional) allocator specified at construction.
376///
377/// See @ref bdlma_sequentialpool
379
380 // PRIVATE TYPES
381
382 /// This `struct` overlays the beginning of each managed block of
383 /// allocated memory, implementing a singly-linked list of managed
384 /// blocks, and thereby enabling constant-time additions to the list of
385 /// blocks.
386 struct Block {
387
388 Block *d_next_p; // next pointer
389 bsls::AlignmentUtil::MaxAlignedType d_memory; // force alignment
390 };
391
392 enum {
393 k_NUM_GEOMETRIC_BIN = sizeof(bsls::Types::size_type) > 4 ? 56 : 31
394 // number of bins available for
395 // geometric growth strategy
396 };
397
398 typedef bsl::uint64_t uint64_t; // to support old toolchains
399
400 // PRIVATE CLASS FUNCTIONS
401
402 static uint64_t initAlwaysUnavailable(bsls::Types::size_type initialSize);
403 /// Calculate the value of `d_alwaysUnavailable` for the specified
404 /// `initialSize`. Optionally specify `maxBufferSize` that reduces the
405 /// maximum allocation size managed via `d_geometricBin`; otherwise
406 /// limited to `1 << k_NUM_GEOMETRIC_BIN`.
407 static uint64_t initAlwaysUnavailable(
408 bsls::Types::size_type initialSize,
409 bsls::Types::size_type maxBufferSize);
410
411 // DATA
412 BufferManager d_bufferManager; // memory manager for
413 // current buffer
414
415 Block *d_head_p; // address of 1st block of
416 // memory (or 0)
417
418 Block **d_freeListPrevAddr_p;
419 // address of the pointer
420 // to the next block of
421 // memory available for
422 // use (which may be 0)
423
424 char *d_geometricBin[k_NUM_GEOMETRIC_BIN];
425 // memory allocated for
426 // geometric growth
427 // strategy
428
429 const uint64_t d_alwaysUnavailable;
430 // bitmask of bins never
431 // available to supply
432 // memory (reflects the
433 // effects of
434 // 'initialSize' and
435 // 'maxBufferSize')
436
437 uint64_t d_unavailable; // bitmask of bins
438 // unavailable for
439 // supplying memory
440
441 uint64_t d_allocated; // bitmask of bins with
442 // allocated memory
443
444 Block *d_largeBlockList_p;
445 // address of 1st block of
446 // memory used to satisfy
447 // allocations not handled
448 // by other strategies (or
449 // 0)
450
451 const bsls::Types::size_type d_constantGrowthSize;
452 // available size from an
453 // allocated block when
454 // using constant growth
455 // and 0 when using
456 // geometric growth
457
458 bslma::Allocator *d_allocator_p; // memory allocator (held,
459 // not owned)
460
461 private:
462 // PRIVATE MANIPULATORS
463
464 /// If the specified `size` is not 0, use the allocator supplied at
465 /// construction to allocate a new internal buffer and return the
466 /// address of a contiguous block of memory of `size` (in bytes) from
467 /// this new buffer, according to the alignment strategy specified at
468 /// construction. If `size` is 0, no memory is allocated and 0 is
469 /// returned.
470 void *allocateNonFastPath(bsls::Types::size_type size);
471
472 // NOT IMPLEMENTED
474 SequentialPool& operator=(const SequentialPool&);
475
476 public:
477 // CREATORS
478
479 explicit SequentialPool(bslma::Allocator *basicAllocator = 0);
481 bslma::Allocator *basicAllocator = 0);
482 explicit SequentialPool(bsls::Alignment::Strategy alignmentStrategy,
483 bslma::Allocator *basicAllocator = 0);
484 /// Create a sequential pool for allocating memory blocks from a
485 /// sequence of dynamically-allocated buffers. Optionally specify a
486 /// `basicAllocator` used to supply memory for the dynamically-allocated
487 /// buffers. If `basicAllocator` is 0, the currently installed default
488 /// allocator is used. Optionally specify a `growthStrategy` used to
489 /// control buffer growth. If no `growthStrategy` is specified,
490 /// geometric growth is used. Optionally specify an `alignmentStrategy`
491 /// used to control alignment of allocated memory blocks. If no
492 /// `alignmentStrategy` is specified, natural alignment is used. An
493 /// implementation-defined value is used as the initial size of the
494 /// internal buffer. Note that no limit is imposed on the size of the
495 /// internal buffers when geometric growth is used. Also note that when
496 /// constant growth is used, the size of the internal buffers will
497 /// always be the same as the implementation-defined value.
499 bsls::Alignment::Strategy alignmentStrategy,
500 bslma::Allocator *basicAllocator = 0);
501
502 explicit SequentialPool(int initialSize);
504 bslma::Allocator *basicAllocator = 0);
506 bsls::BlockGrowth::Strategy growthStrategy,
507 bslma::Allocator *basicAllocator = 0);
509 bsls::Alignment::Strategy alignmentStrategy,
510 bslma::Allocator *basicAllocator = 0);
511 /// Create a sequential pool for allocating memory blocks from a
512 /// sequence of dynamically-allocated buffers, of which the initial
513 /// buffer has the specified `initialSize` (in bytes). Optionally
514 /// specify a `basicAllocator` used to supply memory for the
515 /// dynamically-allocated buffers. If `basicAllocator` is 0, the
516 /// currently installed default allocator is used. Optionally specify a
517 /// `growthStrategy` used to control buffer growth. If no
518 /// `growthStrategy` is specified, geometric growth is used. Optionally
519 /// specify an `alignmentStrategy` used to control alignment of
520 /// allocated memory blocks. If no `alignmentStrategy` is specified,
521 /// natural alignment is used. By specifying an `initialSize`, the
522 /// construction of a sequential pool will incur a memory allocation.
523 /// The behavior is undefined unless `0 < initialSize`. Note that no
524 /// limit is imposed on the size of the internal buffers when geometric
525 /// growth is used. Also note that when constant growth is used, the
526 /// size of the internal buffers will always be the same as
527 /// `initialSize`. Also note that `SequentialPool(int initialSize)` is
528 /// provided to avoid ambiguous definitions.
530 bsls::BlockGrowth::Strategy growthStrategy,
531 bsls::Alignment::Strategy alignmentStrategy,
532 bslma::Allocator *basicAllocator = 0);
533
535 bsls::Types::size_type maxBufferSize,
536 bslma::Allocator *basicAllocator = 0);
538 bsls::Types::size_type maxBufferSize,
539 bsls::BlockGrowth::Strategy growthStrategy,
540 bslma::Allocator *basicAllocator = 0);
542 bsls::Types::size_type maxBufferSize,
543 bsls::Alignment::Strategy alignmentStrategy,
544 bslma::Allocator *basicAllocator = 0);
545 /// Create a sequential pool for allocating memory blocks from a
546 /// sequence of dynamically-allocated buffers, of which the initial
547 /// buffer has the specified `initialSize` (in bytes), and the internal
548 /// buffer growth is limited to the specified `maxBufferSize`.
549 /// Optionally specify a `basicAllocator` used to supply memory for the
550 /// dynamically-allocated buffers. If `basicAllocator` is 0, the
551 /// currently installed default allocator is used. Optionally specify a
552 /// `growthStrategy` used to control buffer growth. If no
553 /// `growthStrategy` is specified, geometric growth is used. Optionally
554 /// specify an `alignmentStrategy` used to control alignment of
555 /// allocated memory blocks. If no `alignmentStrategy` is specified,
556 /// natural alignment is used. The behavior is undefined unless
557 /// `0 < initialSize` and `initialSize <= maxBufferSize`. Note that
558 /// when constant growth is used, the size of the internal buffers will
559 /// always be the same as `initialSize`.
561 bsls::Types::size_type maxBufferSize,
562 bsls::BlockGrowth::Strategy growthStrategy,
563 bsls::Alignment::Strategy alignmentStrategy,
564 bslma::Allocator *basicAllocator = 0);
565
566 /// Create a sequential pool for allocating memory blocks from a
567 /// sequence of dynamically-allocated buffers, of which the initial
568 /// buffer has the specified `initialSize` (in bytes), the internal
569 /// buffer growth is limited to the specified `maxBufferSize`, the
570 /// specified `growthStrategy` is used to control buffer growth, and the
571 /// specified `alignmentStrategy` is used to control alignment of
572 /// allocated memory blocks. Allocate the initial buffer only if the
573 /// specified `allocateInitialBuffer` is `true`. Optionally specify a
574 /// `basicAllocator` used to supply memory for the dynamically-allocated
575 /// buffers. If `basicAllocator` is 0, the currently installed default
576 /// allocator is used. The behavior is undefined unless
577 /// `0 < initialSize` and `initialSize <= maxBufferSize`. Note that
578 /// when constant growth is used, the size of the internal buffers will
579 /// always be the same as `initialSize`.
581 bsls::Types::size_type maxBufferSize,
582 bsls::BlockGrowth::Strategy growthStrategy,
583 bsls::Alignment::Strategy alignmentStrategy,
584 bool allocateInitialBuffer,
585 bslma::Allocator *basicAllocator = 0);
586
587 /// Destroy this sequential pool. All memory allocated by this pool is
588 /// released.
590
591 // MANIPULATORS
592
593 /// Return the address of a contiguous block of memory of the specified
594 /// `size` (in bytes) according to the alignment strategy specified at
595 /// construction. If `size` is 0, no memory is allocated and 0 is
596 /// returned. If the allocation request exceeds the remaining free
597 /// memory space in the current internal buffer, use the allocator
598 /// supplied at construction to allocate a new internal buffer, then
599 /// allocate memory from the new buffer.
601
602 /// Return the address of a contiguous block of memory of at least the
603 /// specified `*size` (in bytes), and load the actual amount of memory
604 /// allocated in `*size`. If `*size` is 0, return 0 with no effect. If
605 /// the allocation request exceeds the remaining free memory space in
606 /// the current internal buffer, use the allocator supplied at
607 /// construction to allocate a new internal buffer, then allocate memory
608 /// from the new buffer.
610
611 /// Destroy the specified `object`. Note that memory associated with
612 /// `object` is not deallocated because there is no `deallocate` method
613 /// in `SequentialPool`.
614 template <class TYPE>
615 void deleteObjectRaw(const TYPE *object);
616
617 /// Destroy the specified `object`. Note that this method has the same
618 /// effect as the `deleteObjectRaw` method (since no deallocation is
619 /// involved), and exists for consistency across pools.
620 template <class TYPE>
621 void deleteObject(const TYPE *object);
622
623 /// Release all memory allocated through this pool and return to the
624 /// underlying allocator *all* memory. The pool is reset to its
625 /// default-constructed state, retaining the alignment and growth
626 /// strategies, and the initial and maximum buffer sizes in effect
627 /// following construction. The effect of subsequently - to this
628 /// invocation of `release` - using a pointer obtained from this object
629 /// prior to this call to `release` is undefined.
630 void release();
631
632 /// Release all memory allocated through this pool and return to the
633 /// underlying allocator *only* memory that was allocated outside of the
634 /// typical internal buffer growth of this pool (i.e., large blocks).
635 /// All retained memory will be used to satisfy subsequent allocations.
636 /// The effect of subsequently - to this invocation of `rewind` - using
637 /// a pointer obtained from this object prior to this call to `rewind`
638 /// is undefined.
639 void rewind();
640
641 /// Reserve sufficient memory to satisfy allocation requests for at
642 /// least the specified `numBytes` without replenishment (i.e., without
643 /// dynamic allocation). If `numBytes` is 0, no memory is reserved.
644 /// Note that, when the `numBytes` is distributed over multiple
645 /// `allocate` requests - due to alignment effects - it is possible that
646 /// not all `numBytes` of memory will be used for allocation before
647 /// triggering dynamic allocation.
649
650 /// Reduce the amount of memory allocated at the specified `address` of
651 /// the specified `originalSize` (in bytes) to the specified `newSize`.
652 /// Return `newSize` after truncating, or `originalSize` if the memory
653 /// block at `address` cannot be truncated. This method can only
654 /// `truncate` the memory block returned by the most recent `allocate`
655 /// request from this memory pool, and otherwise has no effect. The
656 /// behavior is undefined unless the memory block at `address` was
657 /// originally allocated by this memory pool, the size of the memory
658 /// block at `address` is `originalSize`, `newSize <= originalSize`, and
659 /// `release` was not called after allocating the memory block at
660 /// `address`.
661 bsls::Types::size_type truncate(void *address,
662 bsls::Types::size_type originalSize,
663 bsls::Types::size_type newSize);
664
665 // Aspects
666
667 /// Return the allocator used by this object to allocate memory. Note
668 /// that this allocator can not be used to deallocate memory allocated
669 /// through this pool.
671};
672
673} // close package namespace
674
675
676// Note that the 'new' and 'delete' operators are declared outside the
677// 'BloombergLP' namespace so that they do not hide the standard placement
678// 'new' and 'delete' operators (i.e.,
679// 'void *operator new(bsl::size_t, void *)' and
680// 'void operator delete(void *)').
681//
682// Also note that only the scalar versions of operators 'new' and 'delete' are
683// provided, because overloading 'new' (and 'delete') with their array versions
684// would cause dangerous ambiguity. Consider what would have happened had we
685// overloaded the array version of operator 'new':
686//..
687// void *operator new[](bsl::size_t size,
688// BloombergLP::bdlma::SequentialPool& pool);
689//..
690// The user of the pool class would have expected to be able to use operator
691// 'new' as follows:
692//..
693// new (*pool) my_Type[...];
694//..
695// The problem is that this expression returns an array that cannot be safely
696// deallocated. On the one hand, there is no syntax in C++ to invoke an
697// overloaded 'operator delete'; on the other hand, the pointer returned by
698// operator 'new' cannot be passed to the 'deallocate' method directly because
699// the pointer is different from the one returned by the 'allocate' method.
700// The compiler offsets the value of this pointer by a header, which is used to
701// maintain the number of objects in the array (so that the 'operator delete'
702// can destroy the right number of objects).
703
704// FREE OPERATORS
705
706/// Return a block of memory of the specified `size` (in bytes) allocated
707/// from the specified `pool`. Note that an object may allocate additional
708/// memory internally, requiring the allocator to be passed in as a
709/// constructor argument:
710/// @code
711/// my_Type *newMyType(bdlma::SequentialPool *pool,
712/// bslma::Allocator *basicAllocator)
713/// {
714/// return new (*pool) my_Type(..., basicAllocator);
715/// }
716/// @endcode
717/// Also note that the analogous version of operator `delete` should not be
718/// called directly. Instead, this component provides a static template
719/// member function, `deleteObject`, parameterized by `TYPE` that performs
720/// the following:
721/// @code
722/// void deleteMyType(bdlma::SequentialPool *pool, my_Type *t)
723/// {
724/// t->~my_Type();
725/// }
726/// @endcode
727void *operator new(bsl::size_t size, BloombergLP::bdlma::SequentialPool& pool);
728
729/// Use the specified `pool` to deallocate the memory at the specified
730/// `address`. The behavior is undefined unless `address` was allocated
731/// using `pool` and has not already been deallocated. This operator is
732/// supplied solely to allow the compiler to arrange for it to be called in
733/// case of an exception.
734void operator delete(void *address, BloombergLP::bdlma::SequentialPool& pool);
735
736// ============================================================================
737// INLINE DEFINITIONS
738// ============================================================================
739
740
741namespace bdlma {
742
743 // --------------------
744 // class SequentialPool
745 // --------------------
746
747// CREATORS
748inline
753
754// MANIPULATORS
755inline
757{
758 void *result = d_bufferManager.allocate(size);
760 return result; // RETURN
761 }
762
763 return allocateNonFastPath(size);
764}
765
766inline
768{
769 BSLS_ASSERT(size);
770
771 void *result = allocate(*size);
773 *size = d_bufferManager.expand(result, *size);
774 }
775
776 return result;
777}
778
779template <class TYPE>
780inline
781void SequentialPool::deleteObjectRaw(const TYPE *object)
782{
783 if (0 != object) {
784#ifndef BSLS_PLATFORM_CMP_SUN
785 object->~TYPE();
786#else
787 const_cast<TYPE *>(object)->~TYPE();
788#endif
789 }
790}
791
792template <class TYPE>
793inline
794void SequentialPool::deleteObject(const TYPE *object)
795{
796 deleteObjectRaw(object);
797}
798
799inline
801 void *address,
802 bsls::Types::size_type originalSize,
804{
805 BSLS_ASSERT(address);
806 BSLS_ASSERT(newSize <= originalSize);
807
808 return d_bufferManager.truncate(address, originalSize, newSize);
809}
810
811// Aspects
812
813inline
815{
816 return d_allocator_p;
817}
818
819} // close package namespace
820
821
822// FREE OPERATORS
823inline
824void *operator new(bsl::size_t size, BloombergLP::bdlma::SequentialPool& pool)
825{
826 return pool.allocate(size);
827}
828
829inline
830void operator delete(void *, BloombergLP::bdlma::SequentialPool&)
831{
832 // NOTE: there is no deallocation from this allocation mechanism.
833}
834
835#endif
836
837// ----------------------------------------------------------------------------
838// Copyright 2016 Bloomberg Finance L.P.
839//
840// Licensed under the Apache License, Version 2.0 (the "License");
841// you may not use this file except in compliance with the License.
842// You may obtain a copy of the License at
843//
844// http://www.apache.org/licenses/LICENSE-2.0
845//
846// Unless required by applicable law or agreed to in writing, software
847// distributed under the License is distributed on an "AS IS" BASIS,
848// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
849// See the License for the specific language governing permissions and
850// limitations under the License.
851// ----------------------------- END-OF-FILE ----------------------------------
852
853/** @} */
854/** @} */
855/** @} */
Definition bdlma_buffermanager.h:307
bsls::Types::size_type truncate(void *address, bsls::Types::size_type originalSize, bsls::Types::size_type newSize)
bsls::Types::size_type expand(void *address, bsls::Types::size_type size)
void * allocate(bsls::Types::size_type size)
Definition bdlma_buffermanager.h:523
Definition bdlma_sequentialpool.h:378
SequentialPool(bsls::Types::size_type initialSize, bsls::Types::size_type maxBufferSize, bsls::BlockGrowth::Strategy growthStrategy, bslma::Allocator *basicAllocator=0)
void deleteObjectRaw(const TYPE *object)
Definition bdlma_sequentialpool.h:781
SequentialPool(bsls::Types::size_type initialSize, bslma::Allocator *basicAllocator=0)
void deleteObject(const TYPE *object)
Definition bdlma_sequentialpool.h:794
SequentialPool(bsls::Types::size_type initialSize, bsls::Types::size_type maxBufferSize, bslma::Allocator *basicAllocator=0)
~SequentialPool()
Definition bdlma_sequentialpool.h:749
SequentialPool(bsls::BlockGrowth::Strategy growthStrategy, bsls::Alignment::Strategy alignmentStrategy, bslma::Allocator *basicAllocator=0)
void reserveCapacity(bsls::Types::size_type numBytes)
SequentialPool(bsls::Types::size_type initialSize, bsls::Types::size_type maxBufferSize, bsls::BlockGrowth::Strategy growthStrategy, bsls::Alignment::Strategy alignmentStrategy, bool allocateInitialBuffer, bslma::Allocator *basicAllocator=0)
bslma::Allocator * allocator() const
Definition bdlma_sequentialpool.h:814
SequentialPool(bsls::Types::size_type initialSize, bsls::Types::size_type maxBufferSize, bsls::Alignment::Strategy alignmentStrategy, bslma::Allocator *basicAllocator=0)
SequentialPool(bsls::Types::size_type initialSize, bsls::Alignment::Strategy alignmentStrategy, bslma::Allocator *basicAllocator=0)
SequentialPool(int initialSize)
SequentialPool(bsls::Alignment::Strategy alignmentStrategy, bslma::Allocator *basicAllocator=0)
SequentialPool(bsls::Types::size_type initialSize, bsls::Types::size_type maxBufferSize, bsls::BlockGrowth::Strategy growthStrategy, bsls::Alignment::Strategy alignmentStrategy, bslma::Allocator *basicAllocator=0)
SequentialPool(bsls::Types::size_type initialSize, bsls::BlockGrowth::Strategy growthStrategy, bslma::Allocator *basicAllocator=0)
SequentialPool(bslma::Allocator *basicAllocator=0)
SequentialPool(bsls::BlockGrowth::Strategy growthStrategy, bslma::Allocator *basicAllocator=0)
void * allocate(bsls::Types::size_type size)
Definition bdlma_sequentialpool.h:756
SequentialPool(bsls::Types::size_type initialSize, bsls::BlockGrowth::Strategy growthStrategy, bsls::Alignment::Strategy alignmentStrategy, bslma::Allocator *basicAllocator=0)
bsls::Types::size_type truncate(void *address, bsls::Types::size_type originalSize, bsls::Types::size_type newSize)
Definition bdlma_sequentialpool.h:800
void * allocateAndExpand(bsls::Types::size_type *size)
Definition bdlma_sequentialpool.h:767
Definition bslma_allocator.h:457
virtual void * allocate(size_type size)=0
#define BSLS_ASSERT(X)
Definition bsls_assert.h:1804
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
#define BSLS_PERFORMANCEHINT_PREDICT_LIKELY(expr)
Definition bsls_performancehint.h:451
Definition bdlma_alignedallocator.h:276
AlignmentToType< BSLS_MAX_ALIGNMENT >::Type MaxAlignedType
Definition bsls_alignmentutil.h:282
Strategy
Types of alignment strategy.
Definition bsls_alignment.h:239
Strategy
Definition bsls_blockgrowth.h:169
std::size_t size_type
Definition bsls_types.h:124