BDE 4.39.x Production Release
Loading...
Searching...
No Matches
bslma_sequentialpool.h
Go to the documentation of this file.
1/// @file bslma_sequentialpool.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bslma_sequentialpool.h -*-C++-*-
8#ifndef INCLUDED_BSLMA_SEQUENTIALPOOL
9#define INCLUDED_BSLMA_SEQUENTIALPOOL
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bslma_sequentialpool bslma_sequentialpool
15/// @brief <span style="color: var(--deprecated-color-dark)">DEPRECATED:</span> Provide fast variable-size memory pool with allocation methods.
16/// @addtogroup bsl
17/// @{
18/// @addtogroup bslma
19/// @{
20/// @addtogroup bslma_sequentialpool
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bslma_sequentialpool-purpose"> Purpose</a>
25/// * <a href="#bslma_sequentialpool-classes"> Classes </a>
26/// * <a href="#bslma_sequentialpool-description"> Description </a>
27/// * <a href="#bslma_sequentialpool-alignment-strategy"> Alignment Strategy </a>
28/// * <a href="#bslma_sequentialpool-optional-buffer-parameter"> Optional buffer Parameter </a>
29/// * <a href="#bslma_sequentialpool-optional-initialsize-parameter"> Optional initialSize Parameter </a>
30/// * <a href="#bslma_sequentialpool-internal-buffer-growth"> Internal Buffer Growth </a>
31/// * <a href="#bslma_sequentialpool-usage"> Usage </a>
32///
33/// # Purpose {#bslma_sequentialpool-purpose}
34/// Provide fast variable-size memory pool with allocation methods.
35///
36/// @deprecated Use @ref bdlma_sequentialpool instead.
37///
38/// # Classes {#bslma_sequentialpool-classes}
39///
40/// - bslma::SequentialPool: fast variable-size memory pool
41///
42/// @see bdlma_sequentialpool
43///
44/// # Description {#bslma_sequentialpool-description}
45/// This component implements a memory pool,
46/// `bslma::SequentialPool`, that dispenses memory blocks of any requested size
47/// from an internal buffer or an optional user-supplied buffer. If an
48/// allocation request exceeds the remaining free memory space in the pool, the
49/// pool either replenishes its buffer with new memory to satisfy the request,
50/// or returns a separate memory block, depending on whether the request size
51/// exceeds an optionally specified maximum buffer size. By default, buffer
52/// growth is not capped. The `release` method releases all memory allocated
53/// through this pool, as does the destructor. Note, however, that individual
54/// allocated blocks of memory cannot be separately deallocated.
55///
56/// ## Alignment Strategy {#bslma_sequentialpool-alignment-strategy}
57///
58///
59/// The `bslma::SequentialPool` allocates memory using one of the two alignment
60/// strategies (defined in @ref bslma_bufferallocator ) optionally specified at
61/// construction: 1) MAXIMUM ALIGNMENT or 2) NATURAL ALIGNMENT.
62///
63/// 1. MAXIMUM ALIGNMENT: This strategy always allocates memory aligned with the
64/// most restrictive alignment on the host platform. The value is defined by
65/// `bsls::AlignmentUtil::BSLS_MAX_ALIGNMENT`.
66/// 2. NATURAL ALIGNMENT: This strategy allocates memory whose alignment depends
67/// on the requested number of bytes. An instance of a fundamental type
68/// (`int`, etc.) is *naturally* *aligned* when it's size evenly divides its
69/// address. An instance of an aggregate type has natural alignment if the
70/// alignment of the most-restrictively aligned sub-object evenly divides the
71/// address of the aggregate. Natural alignment is always at least as
72/// restrictive as the compiler's required alignment. When only the size of
73/// an aggregate is known, and not its composition, we compute the alignment
74/// by finding the largest integral power of 2 (up to and including
75/// `bsls::AlignmentUtil::BSLS_MAX_ALIGNMENT`) that divides the requested
76/// (non-zero) number of bytes. This computed alignment is guaranteed to be
77/// at least as restrictive as any sub-object within the aggregate.
78///
79/// The default strategy is NATURAL ALIGNMENT.
80///
81/// ## Optional buffer Parameter {#bslma_sequentialpool-optional-buffer-parameter}
82///
83///
84/// A buffer can be supplied to a `bslma::SequentialPool` object at construction
85/// in which case the pool will try to satisfy allocation requests using this
86/// buffer before switching to a dynamically-allocated internal pool. Once the
87/// object is using an internal pool, it will not try to satisfy any subsequent
88/// allocation requests from the supplied buffer. Note that the pool does *not*
89/// take ownership of the buffer. Also note that `bufferSize` may be specified
90/// using a positive or negative value to indicate a buffer growth strategy (see
91/// "Internal Buffer Growth").
92///
93/// ## Optional initialSize Parameter {#bslma_sequentialpool-optional-initialsize-parameter}
94///
95///
96/// In lieu of an externally-supplied buffer, a value for the `initialSize`
97/// parameter may be supplied at construction to specify the initial size of the
98/// internal pool. If neither a buffer nor an `initialSize` is specified, an
99/// implementation-defined value is used for an initial size of the internal
100/// pool. Note that `initialSize` may be specified using a positive or negative
101/// value to indicate a buffer growth strategy (see "Internal Buffer Growth").
102///
103/// ## Internal Buffer Growth {#bslma_sequentialpool-internal-buffer-growth}
104///
105///
106/// A `bslma::SequentialPool` replenishes its internal buffer if the current
107/// buffer cannot satisfy an allocation request. It does so by one of two
108/// growth strategies:
109///
110/// Constant Growth: The new buffer is always of the same size as the current
111/// buffer (possibly supplied at construction).
112///
113/// Geometric Growth: The new buffer will be geometrically larger than the
114/// current buffer up to an optionally-specified maximum limit.
115///
116/// If a `bufferSize` (and corresponding `buffer`) or `initialSize` is supplied
117/// at construction, the sign of its value implicitly specifies which growth
118/// strategy to use. A positive value indicates Constant Growth, whereas a a
119/// negative value indicates Geometric Growth. If neither `bufferSize` nor
120/// `initialSize` is supplied, Geometric Growth is used. The optional
121/// `maxBufferSize` parameter may be used to place a cap on Geometric Growth
122/// (`maxBufferSize` is ignored if Constant Growth is in effect). If no value
123/// is specified for `maxBufferSize`, there is no cap on Geometric Growth. Note
124/// that `reserveCapacity` always ensures that the requested number of bytes is
125/// available (allocating a new internal pool if necessary) irrespective of
126/// whether the size of the request exceeds `maxBufferSize`.
127///
128/// ## Usage {#bslma_sequentialpool-usage}
129///
130///
131/// The `bslma::SequentialPool` can be used to allocate memory for containers of
132/// non-homogeneous elements, such as `MyList` below. Note that the use of a
133/// sequential pool allows the `operator=` and `removeAll` methods to quickly
134/// deallocate memory of all elements by calling the `release` method of the
135/// pool. Similarly, the destructor of `MyList` simply allows the pool's
136/// destructor to deallocate memory for all elements:
137/// @code
138/// // MyList.h
139/// #include <bslma_allocator.fwd.h>
140/// #include <bslma_sequentialpool.h>
141/// #include <bsls_types.h>
142///
143/// class MyList {
144/// char *d_typeArray_p;
145/// void **d_list_p;
146/// int d_length;
147/// int d_size;
148/// bslma::Allocator *d_allocator_p;
149/// bslma::SequentialPool d_pool;
150///
151/// private:
152/// // NOT IMPLEMENTED
153/// MyList(const MyList&);
154///
155/// private:
156/// MyList(char* buffer, int bufferSize, bslma::Allocator *basicAllocator);
157/// void increaseSize();
158///
159/// public:
160/// enum Type { INT, DOUBLE, INT64 };
161///
162/// MyList(bslma::Allocator *basicAllocator);
163///
164/// ~MyList();
165/// MyList& operator=(const MyList& rhs);
166/// void append(int value);
167/// void append(double value);
168/// void append(bsls::Types::Int64 value);
169/// void removeAll();
170///
171/// const int *theInt(int index) const;
172/// const double *theDouble(int index) const;
173/// const bsls::Types::Int64 *theInt64(int index) const;
174/// const Type type(int index) const;
175/// int length() const;
176/// };
177///
178/// inline
179/// void MyList::removeAll()
180/// {
181/// d_pool.release();
182/// d_length = 0;
183/// }
184///
185/// inline
186/// const int *MyList::theInt(int index) const
187/// {
188/// return (int *) d_list_p[index];
189/// }
190///
191/// inline
192/// const double *MyList::theDouble(int index) const
193/// {
194/// return (double *) d_list_p[index];
195/// }
196///
197/// inline
198/// const bsls::Types::Int64 *MyList::theInt64(int index) const
199/// {
200/// return (bsls::Types::Int64 *) d_list_p[index];
201/// }
202///
203/// inline
204/// const MyList::Type MyList::type(int index) const
205/// {
206/// return (Type) d_typeArray_p[index];
207/// }
208///
209/// inline
210/// int MyList::length() const
211/// {
212/// return d_length;
213/// }
214///
215/// // ...
216///
217/// // MyList.cpp
218/// #include <MyList.h>
219/// #include <bslma_allocator.h>
220///
221/// enum { INITIAL_SIZE = 1, GROW_FACTOR = 2 };
222///
223/// /// Copy the value of the specified `srcElement` of the specified `type`
224/// /// to the specified `index` position in the specified `list`. Use the
225/// /// specified `pool` to supply memory.
226/// static
227/// void copyElement(void **list, MyList::Type type, int index,
228/// void *srcElement, bslma::SequentialPool *pool)
229/// {
230/// assert(list);
231/// assert(0 <= index);
232/// assert(srcElement);
233/// assert(pool);
234///
235/// typedef bsls::Types::Int64 Int64;
236///
237/// switch (type) {
238/// case MyList::INT:
239/// list[index] = new(pool->allocate(sizeof(int)))
240/// int(*((int *) srcElement));
241/// break;
242/// case MyList::DOUBLE:
243/// list[index] = new(pool->allocate(sizeof(double)))
244/// double(*((double *) srcElement));
245/// break;
246/// case MyList::INT64:
247/// list[index] = new(pool->allocate(sizeof(Int64)))
248/// Int64(*((Int64 *) srcElement));
249/// break;
250/// default:
251/// assert(0 && "ERROR (MyList): Invalid element type.");
252/// }
253/// }
254///
255/// /// Reallocate memory in the specified `list` and `typeArray` using the
256/// /// specified `basicAllocator` and update the specified size to the
257/// /// specified `newSize`. The specified `length` number of leading
258/// /// elements are preserved in `list` and `typeArray`. If `allocate`
259/// /// should throw an exception, this function has no effect. The
260/// /// behavior is undefined unless `1 <= newSize`, `0 <= length`, and
261/// /// `newSize <= length`.
262/// static
263/// void reallocate(void ***list, char **typeArray, int *size,
264/// int newSize, int length, bslma::Allocator *basicAllocator)
265/// {
266/// assert(list);
267/// assert(*list);
268/// assert(typeArray);
269/// assert(*typeArray);
270/// assert(size);
271/// assert(1 <= newSize);
272/// assert(0 <= length);
273/// assert(length <= *size); // sanity check
274/// assert(length <= newSize); // ensure class invariant
275/// assert(basicAllocator);
276///
277/// void **newList =
278/// (void **) basicAllocator->allocate(newSize * sizeof *newList);
279/// char *newTypeArray =
280/// (char *) basicAllocator->allocate(newSize * sizeof *newTypeArray);
281/// memcpy(newList, *list, length * sizeof **list);
282/// memcpy(newTypeArray, *typeArray, length * sizeof **typeArray);
283/// basicAllocator->deallocate(*list);
284/// basicAllocator->deallocate(*typeArray);
285/// *list = newList;
286/// *typeArray = newTypeArray;
287/// *size = newSize;
288/// }
289///
290/// void MyList::increaseSize()
291/// {
292/// int newSize = d_size * GROW_FACTOR;
293/// reallocate(&d_list_p, &d_typeArray_p, &d_size, newSize,
294/// d_length, d_allocator_p);
295/// }
296///
297/// MyList::MyList(char* buffer, int bufferSize,
298/// bslma::Allocator *basicAllocator)
299/// : d_length()
300/// , d_size(MY_INITIAL_SIZE)
301/// , d_pool(buffer, bufferSize, basicAllocator)
302/// , d_allocator_p(basicAllocator)
303/// {
304/// assert(d_allocator_p);
305///
306/// d_typeArray_p =
307/// (char *) d_allocator_p->allocate(d_size * sizeof *d_typeArray_p);
308/// d_list_p =
309/// (void **) d_allocator_p->allocate(d_size * sizeof *d_list_p);
310/// }
311///
312/// MyList::MyList(bslma::Allocator *basicAllocator)
313/// : d_size(INITIAL_SIZE)
314/// , d_length(0)
315/// , d_pool(basicAllocator)
316/// , d_allocator_p(basicAllocator)
317/// {
318/// assert(d_allocator_p);
319///
320/// d_typeArray_p =
321/// (char *) d_allocator_p->allocate(d_size * sizeof *d_typeArray_p);
322/// d_list_p =
323/// (void **) d_allocator_p->allocate(d_size * sizeof *d_list_p);
324/// }
325///
326/// MyList::~MyList()
327/// {
328/// assert(d_typeArray_p);
329/// assert(d_list_p);
330/// assert(0 <= d_size);
331/// assert(0 <= d_length); assert(d_length <= d_size);
332/// assert(d_allocator_p);
333///
334/// d_allocator_p->deallocate(d_typeArray_p);
335/// d_allocator_p->deallocate(d_list_p);
336/// }
337///
338/// MyList& MyList::operator=(const MyList& rhs)
339/// {
340/// if (&rhs != this) {
341/// // not aliased
342/// d_pool.release();
343/// d_length = 0;
344///
345/// int newLength = rhs.d_length;
346/// if (newLength > d_size) {
347/// reallocate(&d_list_p, &d_typeArray_p, &d_size,
348/// newLength, d_length, d_allocator_p);
349/// }
350/// for (int i = 0; i < newLength; ++i) {
351/// d_typeArray_p[i] = rhs.d_typeArray_p[i];
352/// copyElement(d_list_p, (Type) d_typeArray_p[i], i,
353/// rhs.d_list_p[i], &d_pool);
354/// }
355/// d_length = newLength;
356/// }
357/// return *this;
358/// }
359///
360/// void MyList::append(int value)
361/// {
362/// if (d_length >= d_size) {
363/// increaseSize();
364/// }
365/// int *item = (int *) d_pool.allocate(sizeof *item);
366/// *item = value;
367/// d_typeArray_p[d_length] = (char) MyList::INT;
368/// d_list_p[d_length++] = item;
369/// }
370///
371/// void MyList::append(double value)
372/// {
373/// if (d_length >= d_size) {
374/// increaseSize();
375/// }
376/// double *item = (double *) d_pool.allocate(sizeof *item);
377/// *item = value;
378/// d_typeArray_p[d_length] = (char) MyList::DOUBLE;
379/// d_list_p[d_length++] = item;
380/// }
381///
382/// void MyList::append(bsls::Types::Int64 value)
383/// {
384/// typedef bsls::Types::Int64 Int64;
385///
386/// if (d_length >= d_size) {
387/// increaseSize();
388/// }
389/// Int64 *item = (Int64 *) d_pool.allocate(sizeof *item);
390/// *item = value;
391/// d_typeArray_p[d_length] = (char) MyList::INT64;
392/// d_list_p[d_length++] = item;
393/// }
394/// @endcode
395/// @}
396/** @} */
397/** @} */
398
399/** @addtogroup bsl
400 * @{
401 */
402/** @addtogroup bslma
403 * @{
404 */
405/** @addtogroup bslma_sequentialpool
406 * @{
407 */
408
409#ifdef BDE_OPENSOURCE_PUBLICATION // DEPRECATED
410#error "bslma_sequentialpool is deprecated"
411#endif
412#include <bslscm_version.h>
413
416
417#include <bsls_platform.h>
418
419#include <cstddef> // for 'std::size_t'
420
421
422
423namespace bslma {
424
425 // ====================
426 // class SequentialPool
427 // ====================
428
429/// This class implements a memory pool that dispenses arbitrarily-sized
430/// blocks of memory from an internal buffer or an optionally user-supplied
431/// buffer. If an allocation request exceeds the remaining free memory
432/// space in the current buffer, the pool either replenishes its buffer with
433/// new memory to satisfy the request, or returns a separate memory block,
434/// depending on whether the request size exceeds an optionally specified
435/// maximum buffer size. By default, buffer growth is not capped. The
436/// `release` method releases all memory allocated through this pool, as
437/// does the destructor. Note, however, that individual allocated blocks of
438/// memory cannot be individually deallocated.
439///
440/// See @ref bslma_sequentialpool
442
443 // TYPES
444 enum GrowthStrategy {
445 // Enumerate the various internal buffer growth strategies.
446
447 CONSTANT, // constant growth
448 GEOMETRIC // geometric growth
449 };
450
451 // DATA
452 char *d_buffer; // holds current free memory
453 // buffer
454
455 int d_cursor; // position of the next
456 // available byte
457
458 int d_bufSize; // current free memory buffer
459 // size
460
462 d_alignmentStrategy; // alignment strategy
463
464 int d_maxBufferSize; // maximum buffer size
465
466 GrowthStrategy d_growthStrategy; // growth strategy
467
469 d_blockList; // provides free memory
470
471 private:
472 // NOT IMPLEMENTED
474 SequentialPool& operator=(const SequentialPool&);
475
476 private:
477 // PRIVATE ACCESSORS
478
479 /// Calculate and return the next buffer size corresponding to a reserve
480 /// or allocation of the specified `size` bytes.
481 int calculateNextBufferSize(int size) const;
482
483 public:
484 // CREATORS
485
486 /// Create a sequential pool for allocating memory blocks from an
487 /// internal buffer. Optionally specify an alignment `strategy` used to
488 /// align allocated memory blocks. If `strategy` is not specified,
489 /// *Natural Alignment* is used. Optionally specify an `initialSize`
490 /// the absolute value of which indicates the initial size (in bytes)
491 /// for the internal buffer. If `initialSize` is not specified, an
492 /// implementation-defined value is used. Optionally specify a
493 /// `basicAllocator` used to supply memory. If `basicAllocator` is 0,
494 /// the currently installed default allocator is used. If an `allocate`
495 /// or `reserveCapacity` request cannot be satisfied from the current
496 /// buffer, a new buffer is allocated, the size of which is determined
497 /// by a buffer growth strategy implied by `initialSize`. If
498 /// `initialSize` was specified and is negative, or if it was *not*
499 /// specified, the buffer growth strategy used is *Geometric Growth*;
500 /// otherwise it is *Constant Growth*. (See the component level
501 /// documentation for further details.) In either case, the new buffer
502 /// will have sufficient capacity to satisfy the request. If *Geometric
503 /// Growth* is in effect, no limit is imposed on the size of buffers.
504 explicit SequentialPool(Allocator *basicAllocator = 0);
507 Allocator *basicAllocator = 0);
508 explicit SequentialPool(int initialSize,
509 Allocator *basicAllocator = 0);
510 SequentialPool(int initialSize,
512 Allocator *basicAllocator = 0);
513
514 /// Create a sequential pool for allocating memory blocks initially from
515 /// the specified `buffer` the size (in bytes) of which is indicated by
516 /// the absolute value of the specified `bufferSize`. Optionally
517 /// specify an alignment `strategy` used to align allocated memory
518 /// blocks. If `strategy` is not specified, *Natural Alignment* is
519 /// used. Optionally specify a `basicAllocator` used to supply memory.
520 /// If `basicAllocator` is 0, the currently installed default allocator
521 /// is used. If an `allocate` or `reserveCapacity` request cannot be
522 /// satisfied from the current buffer, a new buffer is allocated, the
523 /// size of which is determined by a buffer growth strategy implied by
524 /// `bufferSize`. If `bufferSize` is negative, the buffer growth
525 /// strategy used is *Geometric Growth*; otherwise it is *Constant
526 /// Growth*. (See the component level documentation for further
527 /// details.) In either case, the new buffer will have sufficient
528 /// capacity to satisfy the request. If *Geometric Growth* is in
529 /// effect, no limit is imposed on the size of buffers.
530 SequentialPool(char *buffer,
531 int bufferSize,
532 Allocator *basicAllocator = 0);
533 SequentialPool(char *buffer,
534 int bufferSize,
536 Allocator *basicAllocator = 0);
537
538 /// Create a sequential pool for allocating memory blocks from an
539 /// internal buffer the initial size (in bytes) of which is indicated by
540 /// the absolute value of the specified `initialSize`. The specified
541 /// `maxBufferSize` indicates the maximum size (in bytes) allowed for
542 /// internally allocated buffers. Optionally specify an alignment
543 /// `strategy` used to align allocated memory blocks. If `strategy` is
544 /// not specified, *Natural Alignment* is used. Optionally specify a
545 /// `basicAllocator` used to supply memory. If `basicAllocator` is 0,
546 /// the currently installed default allocator is used. If an `allocate`
547 /// or `reserveCapacity` request cannot be satisfied from the current
548 /// buffer, a new buffer is allocated, the size of which is determined
549 /// by a buffer growth strategy implied by `initialSize`. If
550 /// `initialSize` is negative the buffer growth strategy used is
551 /// *Geometric Growth*; otherwise it is *Constant Growth*. (See the
552 /// component level documentation for further details.) In either case,
553 /// the new buffer will have sufficient capacity to satisfy the request.
554 /// If *Geometric Growth* is in effect, the geometric progression of
555 /// buffer sizes is capped at `maxBufferSize`.
556 ///
557 /// \pre The behavior is undefined unless `0 < maxBufferSize`, and `|initialSize| <= maxBufferSize`.
558 ///
559 /// \note Note that `maxBufferSize` is
560 /// ignored if `initialSize > 0`. Also note that `maxBufferSize` may be
561 /// overridden by a sufficiently large value passed to `allocate` or
562 /// `reserveCapacity`.
563 SequentialPool(int initialSize,
564 int maxBufferSize,
565 Allocator *basicAllocator = 0);
566 SequentialPool(int initialSize,
567 int maxBufferSize,
569 Allocator *basicAllocator = 0);
570
571 /// Create a sequential pool for allocating memory blocks initially from
572 /// the specified `buffer` the size (in bytes) of which is indicated by
573 /// the absolute value of the specified `bufferSize`. The specified
574 /// `maxBufferSize` indicates the maximum size (in bytes) allowed for
575 /// internally allocated buffers. Optionally specify an alignment
576 /// `strategy` used to align allocated memory blocks. If `strategy` is
577 /// not specified, *Natural Alignment* is used. Optionally specify a
578 /// `basicAllocator` used to supply memory. If `basicAllocator` is 0,
579 /// the currently installed default allocator is used. If an `allocate`
580 /// or `reserveCapacity` request cannot be satisfied from the current
581 /// buffer, a new buffer is allocated, the size of which is determined
582 /// by a buffer growth strategy implied by `bufferSize`. If
583 /// `bufferSize` is negative, the buffer growth strategy used is
584 /// *Geometric Growth*; otherwise it is *Constant Growth*. (See the
585 /// component level documentation for further details.) In either case,
586 /// the new buffer will have sufficient capacity to satisfy the request.
587 /// If *Geometric Growth* is in effect, the geometric progression of
588 /// buffer sizes is capped at `maxBufferSize`.
589 ///
590 /// \pre The behavior is undefined unless `0 < maxBufferSize`, and `|bufferSize| <= maxBufferSize`.
591 ///
592 /// \note Note that `maxBufferSize` is
593 /// ignored if `bufferSize > 0`. Also note that `maxBufferSize` may be
594 /// overridden by a sufficiently large value passed to `allocate` or
595 /// `reserveCapacity`.
596 SequentialPool(char *buffer,
597 int bufferSize,
598 int maxBufferSize,
599 Allocator *basicAllocator = 0);
600 SequentialPool(char *buffer,
601 int bufferSize,
602 int maxBufferSize,
604 Allocator *basicAllocator = 0);
605
606 /// Destroy this object and release all memory currently allocated
607 /// through this pool.
609
610 // MANIPULATORS
611
612 /// Return memory of the specified `size`. If `size` is 0, no memory is allocated and 0 is returned.
613 ///
614 /// \pre The behavior is undefined unless
615 /// `0 <= size`.
616 void *allocate(int size);
617
618 /// Return memory of at least the specified `*size` and return the
619 /// actual amount of memory allocated in `*size`. If `*size` is 0, no
620 /// memory is allocated and 0 is returned.
621 ///
622 /// \pre The behavior is undefined unless `0 <= *size`.
623 void *allocateAndExpand(int *size);
624
625 /// Return memory of at least the specified `*size` and at most the
626 /// specified `maxNumBytes`. Also return the actual amount of memory
627 /// allocated in `*size`. If `*size` is 0, no memory is allocated and 0 is returned.
628 ///
629 /// \pre The behavior is undefined unless
630 /// `0 <= *size <= maxNumBytes`.
631 void *allocateAndExpand(int *size, int maxNumBytes);
632
633 /// Destroy the specified `object`.
634 /// \note Note that this method is exactly
635 /// the same as the `deleteObjectRaw` method since no deallocation is
636 /// involved. This method exists purely for consistency across pools.
637 template <class TYPE>
638 void deleteObject(const TYPE *object);
639
640 /// Destroy the specified `object`.
641 /// \note Note that the memory is not
642 /// deallocated because there is no `deallocate` method in a
643 /// @ref bslma_sequentialpool .
644 template <class TYPE>
645 void deleteObjectRaw(const TYPE *object);
646
647 /// Increase the amount of memory allocated at the specified `address`
648 /// from the specified `originalNumBytes` to the maximum amount easily
649 /// obtainable. Return the amount of memory available at `address` after the expansion.
650 ///
651 /// \pre The behavior is undefined unless the call to
652 /// this allocator that provided the `address` was performed with the `originalNumBytes`.
653 ///
654 /// \note Note that this function will not expand the
655 /// memory unless there have been no allocations since the allocation
656 /// for `originalNumBytes`.
657 int expand(void *address, int originalNumBytes);
658
659 /// Increase the amount of memory allocated at the specified `address`
660 /// from the specified `originalNumBytes` to the maximum amount easily
661 /// obtainable up to the specified `maxNumBytes`. Return the amount of
662 /// memory available at `address` after the expansion.
663 ///
664 /// \pre The behavior is undefined unless the call to this allocator that provided the
665 /// `address` was performed with the `originalNumBytes` and `originalNumBytes < maxNumBytes`.
666 ///
667 /// \note Note that this function will not
668 /// expand the memory unless there have been no allocations since the
669 /// allocation for `originalNumBytes`.
670 int expand(void *address, int originalNumBytes, int maxNumBytes);
671
672 /// Release all memory currently allocated through this pool.
673 void release();
674
675 /// Reserve sufficient memory to satisfy allocation requests for at
676 /// least the specified `numBytes` without replenishment (i.e., without internal allocation).
677 ///
678 /// \pre The behavior is undefined unless
679 /// `0 <= numBytes`.
680 void reserveCapacity(int numBytes);
681
682 /// Reduce the amount of memory allocated at the specified `address`
683 /// from the specified `originalNumBytes` to the specified
684 /// `newNumBytes`. Return the amount of memory available at `address` after the truncation.
685 ///
686 /// \pre The behavior is undefined unless the call to
687 /// this allocator that provided the `address` was performed with the
688 /// `originalNumBytes` and `newNumBytes <= originalNumBytes`.
689 ///
690 /// \note Note that this function will not truncate the memory unless there have been no
691 /// allocations since the allocation for `originalNumBytes`.
692 int truncate(void *address, int originalNumBytes, int newNumBytes);
693};
694
695} // close package namespace
696
697
698// FREE OPERATORS
699
700// Note that the operators 'new' and 'delete' are declared outside the
701// 'BloombergLP' namespace so that they do not hide the standard placement
702// 'new' and 'delete' operators (i.e., 'void *operator new(size_t, void *)' and
703// 'void operator delete(void *)').
704//
705// Note also that only the scalar versions of operators 'new' and 'delete' are
706// provided, because overloading 'new' (and 'delete') with their array versions
707// would cause dangerous ambiguity. Consider what would have happened had we
708// overloaded the array version of operator 'new':
709//..
710// void *operator new[](std::size_t size,
711// BloombergLP::bslma::Pool& pool)
712//..
713// The user of the pool class would have expected to be able to use
714// 'new-expression':
715//..
716// new (*pool) my_Type[...];
717//..
718// The problem is that this expression returns an array that cannot be safely
719// deallocated. On the one hand there is no syntax in C++ to invoke an
720// overloaded operator delete; on the other hand the pointer returned by the
721// 'new-expression' cannot be passed to the 'deallocate' method directly
722// because the pointer is different from the one returned by the 'allocate'
723// method. The compiler offsets the value of this pointer by an extra header,
724// which the compiler uses to maintain the number of the objects in the array
725// (so that the 'delete-expression' knows how many objects it needs to
726// destroy).
727
728/// Return the memory allocated from the specified `pool`.
729///
730/// \pre The behavior is undefined unless `size` is the same as `objectSize` that `pool` has been constructed with.
731///
732/// \note Note that an object may allocate additional memory
733/// internally, requiring the allocator to be passed in as a constructor
734/// argument:
735/// @code
736/// my_Type *newMyType(bslma::Pool *pool, bslma::Allocator *basicAllocator)
737/// {
738/// return new (*pool) my_Type(..., basicAllocator);
739/// }
740/// @endcode
741/// Note also that the analogous version of operator `delete` should not be
742/// called directly. Instead, this component provides a static template
743/// member function `deleteObject` parameterized by `TYPE` that performs the
744/// following:
745/// @code
746/// void deleteMyType(bslma::Pool *pool, my_Type *t)
747/// {
748/// t->~my_Type();
749/// pool->deallocate(t);
750/// }
751/// @endcode
752inline
753void *operator new(std::size_t size, BloombergLP::bslma::SequentialPool& pool);
754
755/// Use the specified `pool` to deallocate the memory at the specified `address`.
756///
757/// \pre The behavior is undefined unless `address` was allocated
758/// using `pool` and has not already been deallocated. This operator is
759/// supplied solely to allow the compiler to arrange for it to be called in
760/// case of an exception.
761inline
762void operator delete(void *address, BloombergLP::bslma::SequentialPool& pool);
763
764// ============================================================================
765// INLINE DEFINITIONS
766// ============================================================================
767
768
769namespace bslma {
770
771 // --------------
772 // SequentialPool
773 // --------------
774
775// CREATORS
776inline
780
781// MANIPULATORS
782template <class TYPE>
783inline
784void SequentialPool::deleteObjectRaw(const TYPE *object)
785{
786 if (0 != object) {
787#if defined(BSLS_PLATFORM_CMP_SUN) && BSLS_PLATFORM_CMP_VERSION < 0x5130
788 const_cast<TYPE *>(object)->~TYPE();
789#else
790 object->~TYPE();
791#endif
792 }
793}
794
795template <class TYPE>
796inline
797void SequentialPool::deleteObject(const TYPE *object)
798{
799 deleteObjectRaw(object);
800}
801
802} // close package namespace
803
804#ifndef BDE_OPENSOURCE_PUBLICATION // BACKWARD_COMPATIBILITY
805// ============================================================================
806// BACKWARD COMPATIBILITY
807// ============================================================================
808
809/// This alias is defined for backward compatibility.
811#endif // BDE_OPENSOURCE_PUBLICATION -- BACKWARD_COMPATIBILITY
812
813
814
815// FREE OPERATORS
816
817inline
818void *operator new(std::size_t size, BloombergLP::bslma::SequentialPool& pool)
819{
820 return pool.allocate(static_cast<int>(size));
821}
822
823inline
824void operator delete(void *, BloombergLP::bslma::SequentialPool&)
825{
826 // NOTE: there is no deallocation from this allocation mechanism.
827}
828
829#endif
830
831// ----------------------------------------------------------------------------
832// Copyright 2013 Bloomberg Finance L.P.
833//
834// Licensed under the Apache License, Version 2.0 (the "License");
835// you may not use this file except in compliance with the License.
836// You may obtain a copy of the License at
837//
838// http://www.apache.org/licenses/LICENSE-2.0
839//
840// Unless required by applicable law or agreed to in writing, software
841// distributed under the License is distributed on an "AS IS" BASIS,
842// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
843// See the License for the specific language governing permissions and
844// limitations under the License.
845// ----------------------------- END-OF-FILE ----------------------------------
846
847/** @} */
848/** @} */
849/** @} */
Definition bslma_allocator.h:545
AlignmentStrategy
Types of alignment strategy to allocate memory.
Definition bslma_bufferallocator.h:274
Definition bslma_infrequentdeleteblocklist.h:217
Definition bslma_sequentialpool.h:441
SequentialPool(int initialSize, BufferAllocator::AlignmentStrategy strategy, Allocator *basicAllocator=0)
SequentialPool(char *buffer, int bufferSize, BufferAllocator::AlignmentStrategy strategy, Allocator *basicAllocator=0)
void * allocateAndExpand(int *size, int maxNumBytes)
SequentialPool(int initialSize, Allocator *basicAllocator=0)
void deleteObjectRaw(const TYPE *object)
Definition bslma_sequentialpool.h:784
SequentialPool(char *buffer, int bufferSize, Allocator *basicAllocator=0)
void reserveCapacity(int numBytes)
SequentialPool(int initialSize, int maxBufferSize, Allocator *basicAllocator=0)
~SequentialPool()
Definition bslma_sequentialpool.h:777
int truncate(void *address, int originalNumBytes, int newNumBytes)
SequentialPool(BufferAllocator::AlignmentStrategy strategy, Allocator *basicAllocator=0)
SequentialPool(int initialSize, int maxBufferSize, BufferAllocator::AlignmentStrategy strategy, Allocator *basicAllocator=0)
int expand(void *address, int originalNumBytes)
void * allocateAndExpand(int *size)
void deleteObject(const TYPE *object)
Definition bslma_sequentialpool.h:797
void * allocate(int size)
SequentialPool(char *buffer, int bufferSize, int maxBufferSize, Allocator *basicAllocator=0)
void release()
Release all memory currently allocated through this pool.
SequentialPool(Allocator *basicAllocator=0)
SequentialPool(char *buffer, int bufferSize, int maxBufferSize, BufferAllocator::AlignmentStrategy strategy, Allocator *basicAllocator=0)
int expand(void *address, int originalNumBytes, int maxNumBytes)
bslma::SequentialPool bslma_SequentialPool
This alias is defined for backward compatibility.
Definition bslma_sequentialpool.h:810
#define BSLS_IDENT(str)
BSLS_IDENT() - insert string into .comment binary segment (if supported)
Definition bsls_ident.h:238
Definition baljsn_encoder_testtypes.h:76