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