BDE 4.14.0 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 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/// // NOT IMPLEMENTED
152/// MyList(const MyList&);
153///
154/// private:
155/// MyList(char* buffer, int bufferSize, bslma::Allocator *basicAllocator);
156/// void increaseSize();
157///
158/// public:
159/// enum Type { INT, DOUBLE, INT64 };
160///
161/// MyList(bslma::Allocator *basicAllocator);
162///
163/// ~MyList();
164/// MyList& operator=(const MyList& rhs);
165/// void append(int value);
166/// void append(double value);
167/// void append(bsls::Types::Int64 value);
168/// void removeAll();
169///
170/// const int *theInt(int index) const;
171/// const double *theDouble(int index) const;
172/// const bsls::Types::Int64 *theInt64(int index) const;
173/// const Type type(int index) const;
174/// int length() const;
175/// };
176///
177/// inline
178/// void MyList::removeAll()
179/// {
180/// d_pool.release();
181/// d_length = 0;
182/// }
183///
184/// inline
185/// const int *MyList::theInt(int index) const
186/// {
187/// return (int *) d_list_p[index];
188/// }
189///
190/// inline
191/// const double *MyList::theDouble(int index) const
192/// {
193/// return (double *) d_list_p[index];
194/// }
195///
196/// inline
197/// const bsls::Types::Int64 *MyList::theInt64(int index) const
198/// {
199/// return (bsls::Types::Int64 *) d_list_p[index];
200/// }
201///
202/// inline
203/// const MyList::Type MyList::type(int index) const
204/// {
205/// return (Type) d_typeArray_p[index];
206/// }
207///
208/// inline
209/// int MyList::length() const
210/// {
211/// return d_length;
212/// }
213///
214/// // ...
215///
216/// // MyList.cpp
217/// #include <MyList.h>
218/// #include <bslma_allocator.h>
219///
220/// enum { INITIAL_SIZE = 1, GROW_FACTOR = 2 };
221///
222/// /// Copy the value of the specified `srcElement` of the specified `type`
223/// /// to the specified `index` position in the specified `list`. Use the
224/// /// specified `pool` to supply memory.
225/// static
226/// void copyElement(void **list, MyList::Type type, int index,
227/// void *srcElement, bslma::SequentialPool *pool)
228/// {
229/// assert(list);
230/// assert(0 <= index);
231/// assert(srcElement);
232/// assert(pool);
233///
234/// typedef bsls::Types::Int64 Int64;
235///
236/// switch (type) {
237/// case MyList::INT:
238/// list[index] = new(pool->allocate(sizeof(int)))
239/// int(*((int *) srcElement));
240/// break;
241/// case MyList::DOUBLE:
242/// list[index] = new(pool->allocate(sizeof(double)))
243/// double(*((double *) srcElement));
244/// break;
245/// case MyList::INT64:
246/// list[index] = new(pool->allocate(sizeof(Int64)))
247/// Int64(*((Int64 *) srcElement));
248/// break;
249/// default:
250/// assert(0 && "ERROR (MyList): Invalid element type.");
251/// }
252/// }
253///
254/// /// Reallocate memory in the specified `list` and `typeArray` using the
255/// /// specified `basicAllocator` and update the specified size to the
256/// /// specified `newSize`. The specified `length` number of leading
257/// /// elements are preserved in `list` and `typeArray`. If `allocate`
258/// /// should throw an exception, this function has no effect. The
259/// /// behavior is undefined unless `1 <= newSize`, `0 <= length`, and
260/// /// `newSize <= length`.
261/// static
262/// void reallocate(void ***list, char **typeArray, int *size,
263/// int newSize, int length, bslma::Allocator *basicAllocator)
264/// {
265/// assert(list);
266/// assert(*list);
267/// assert(typeArray);
268/// assert(*typeArray);
269/// assert(size);
270/// assert(1 <= newSize);
271/// assert(0 <= length);
272/// assert(length <= *size); // sanity check
273/// assert(length <= newSize); // ensure class invariant
274/// assert(basicAllocator);
275///
276/// void **newList =
277/// (void **) basicAllocator->allocate(newSize * sizeof *newList);
278/// char *newTypeArray =
279/// (char *) basicAllocator->allocate(newSize * sizeof *newTypeArray);
280/// memcpy(newList, *list, length * sizeof **list);
281/// memcpy(newTypeArray, *typeArray, length * sizeof **typeArray);
282/// basicAllocator->deallocate(*list);
283/// basicAllocator->deallocate(*typeArray);
284/// *list = newList;
285/// *typeArray = newTypeArray;
286/// *size = newSize;
287/// }
288///
289/// void MyList::increaseSize()
290/// {
291/// int newSize = d_size * GROW_FACTOR;
292/// reallocate(&d_list_p, &d_typeArray_p, &d_size, newSize,
293/// d_length, d_allocator_p);
294/// }
295///
296/// MyList::MyList(char* buffer, int bufferSize,
297/// bslma::Allocator *basicAllocator)
298/// : d_length()
299/// , d_size(MY_INITIAL_SIZE)
300/// , d_pool(buffer, bufferSize, basicAllocator)
301/// , d_allocator_p(basicAllocator)
302/// {
303/// assert(d_allocator_p);
304///
305/// d_typeArray_p =
306/// (char *) d_allocator_p->allocate(d_size * sizeof *d_typeArray_p);
307/// d_list_p =
308/// (void **) d_allocator_p->allocate(d_size * sizeof *d_list_p);
309/// }
310///
311/// MyList::MyList(bslma::Allocator *basicAllocator)
312/// : d_size(INITIAL_SIZE)
313/// , d_length(0)
314/// , d_pool(basicAllocator)
315/// , d_allocator_p(basicAllocator)
316/// {
317/// assert(d_allocator_p);
318///
319/// d_typeArray_p =
320/// (char *) d_allocator_p->allocate(d_size * sizeof *d_typeArray_p);
321/// d_list_p =
322/// (void **) d_allocator_p->allocate(d_size * sizeof *d_list_p);
323/// }
324///
325/// MyList::~MyList()
326/// {
327/// assert(d_typeArray_p);
328/// assert(d_list_p);
329/// assert(0 <= d_size);
330/// assert(0 <= d_length); assert(d_length <= d_size);
331/// assert(d_allocator_p);
332///
333/// d_allocator_p->deallocate(d_typeArray_p);
334/// d_allocator_p->deallocate(d_list_p);
335/// }
336///
337/// MyList& MyList::operator=(const MyList& rhs)
338/// {
339/// if (&rhs != this) {
340/// // not aliased
341/// d_pool.release();
342/// d_length = 0;
343///
344/// int newLength = rhs.d_length;
345/// if (newLength > d_size) {
346/// reallocate(&d_list_p, &d_typeArray_p, &d_size,
347/// newLength, d_length, d_allocator_p);
348/// }
349/// for (int i = 0; i < newLength; ++i) {
350/// d_typeArray_p[i] = rhs.d_typeArray_p[i];
351/// copyElement(d_list_p, (Type) d_typeArray_p[i], i,
352/// rhs.d_list_p[i], &d_pool);
353/// }
354/// d_length = newLength;
355/// }
356/// return *this;
357/// }
358///
359/// void MyList::append(int value)
360/// {
361/// if (d_length >= d_size) {
362/// increaseSize();
363/// }
364/// int *item = (int *) d_pool.allocate(sizeof *item);
365/// *item = value;
366/// d_typeArray_p[d_length] = (char) MyList::INT;
367/// d_list_p[d_length++] = item;
368/// }
369///
370/// void MyList::append(double value)
371/// {
372/// if (d_length >= d_size) {
373/// increaseSize();
374/// }
375/// double *item = (double *) d_pool.allocate(sizeof *item);
376/// *item = value;
377/// d_typeArray_p[d_length] = (char) MyList::DOUBLE;
378/// d_list_p[d_length++] = item;
379/// }
380///
381/// void MyList::append(bsls::Types::Int64 value)
382/// {
383/// typedef bsls::Types::Int64 Int64;
384///
385/// if (d_length >= d_size) {
386/// increaseSize();
387/// }
388/// Int64 *item = (Int64 *) d_pool.allocate(sizeof *item);
389/// *item = value;
390/// d_typeArray_p[d_length] = (char) MyList::INT64;
391/// d_list_p[d_length++] = item;
392/// }
393/// @endcode
394/// @}
395/** @} */
396/** @} */
397
398/** @addtogroup bsl
399 * @{
400 */
401/** @addtogroup bslma
402 * @{
403 */
404/** @addtogroup bslma_sequentialpool
405 * @{
406 */
407
408#ifdef BDE_OPENSOURCE_PUBLICATION // DEPRECATED
409#error "bslma_sequentialpool is deprecated"
410#endif
411#include <bslscm_version.h>
412
415
416#include <bsls_platform.h>
417
418#include <cstddef> // for 'std::size_t'
419
420
421
422namespace bslma {
423
424 // ====================
425 // class SequentialPool
426 // ====================
427
428/// This class implements a memory pool that dispenses arbitrarily-sized
429/// blocks of memory from an internal buffer or an optionally user-supplied
430/// buffer. If an allocation request exceeds the remaining free memory
431/// space in the current buffer, the pool either replenishes its buffer with
432/// new memory to satisfy the request, or returns a separate memory block,
433/// depending on whether the request size exceeds an optionally specified
434/// maximum buffer size. By default, buffer growth is not capped. The
435/// `release` method releases all memory allocated through this pool, as
436/// does the destructor. Note, however, that individual allocated blocks of
437/// memory cannot be individually deallocated.
438///
439/// See @ref bslma_sequentialpool
441
442 // TYPES
443 enum GrowthStrategy {
444 // Enumerate the various internal buffer growth strategies.
445
446 CONSTANT, // constant growth
447 GEOMETRIC // geometric growth
448 };
449
450 // DATA
451 char *d_buffer; // holds current free memory
452 // buffer
453
454 int d_cursor; // position of the next
455 // available byte
456
457 int d_bufSize; // current free memory buffer
458 // size
459
461 d_alignmentStrategy; // alignment strategy
462
463 int d_maxBufferSize; // maximum buffer size
464
465 GrowthStrategy d_growthStrategy; // growth strategy
466
468 d_blockList; // provides free memory
469
470 // NOT IMPLEMENTED
472 SequentialPool& operator=(const SequentialPool&);
473
474 private:
475 // PRIVATE ACCESSORS
476
477 /// Calculate and return the next buffer size corresponding to a reserve
478 /// or allocation of the specified `size` bytes.
479 int calculateNextBufferSize(int size) const;
480
481 public:
482 // CREATORS
483
484 explicit SequentialPool(Allocator *basicAllocator = 0);
487 Allocator *basicAllocator = 0);
488 explicit SequentialPool(int initialSize,
489 Allocator *basicAllocator = 0);
490 /// Create a sequential pool for allocating memory blocks from an
491 /// internal buffer. Optionally specify an alignment `strategy` used to
492 /// align allocated memory blocks. If `strategy` is not specified,
493 /// *Natural Alignment* is used. Optionally specify an `initialSize`
494 /// the absolute value of which indicates the initial size (in bytes)
495 /// for the internal buffer. If `initialSize` is not specified, an
496 /// implementation-defined value is used. Optionally specify a
497 /// `basicAllocator` used to supply memory. If `basicAllocator` is 0,
498 /// the currently installed default allocator is used. If an `allocate`
499 /// or `reserveCapacity` request cannot be satisfied from the current
500 /// buffer, a new buffer is allocated, the size of which is determined
501 /// by a buffer growth strategy implied by `initialSize`. If
502 /// `initialSize` was specified and is negative, or if it was *not*
503 /// specified, the buffer growth strategy used is *Geometric Growth*;
504 /// otherwise it is *Constant Growth*. (See the component level
505 /// documentation for further details.) In either case, the new buffer
506 /// will have sufficient capacity to satisfy the request. If *Geometric
507 /// Growth* is in effect, no limit is imposed on the size of buffers.
508 SequentialPool(int initialSize,
510 Allocator *basicAllocator = 0);
511
512 SequentialPool(char *buffer,
513 int bufferSize,
514 Allocator *basicAllocator = 0);
515 /// Create a sequential pool for allocating memory blocks initially from
516 /// the specified `buffer` the size (in bytes) of which is indicated by
517 /// the absolute value of the specified `bufferSize`. Optionally
518 /// specify an alignment `strategy` used to align allocated memory
519 /// blocks. If `strategy` is not specified, *Natural Alignment* is
520 /// used. Optionally specify a `basicAllocator` used to supply memory.
521 /// If `basicAllocator` is 0, the currently installed default allocator
522 /// is used. If an `allocate` or `reserveCapacity` request cannot be
523 /// satisfied from the current buffer, a new buffer is allocated, the
524 /// size of which is determined by a buffer growth strategy implied by
525 /// `bufferSize`. If `bufferSize` is negative, the buffer growth
526 /// strategy used is *Geometric Growth*; otherwise it is *Constant
527 /// Growth*. (See the component level documentation for further
528 /// details.) In either case, the new buffer will have sufficient
529 /// capacity to satisfy the request. If *Geometric Growth* is in
530 /// effect, no limit is imposed on the size of buffers.
531 SequentialPool(char *buffer,
532 int bufferSize,
534 Allocator *basicAllocator = 0);
535
536 SequentialPool(int initialSize,
537 int maxBufferSize,
538 Allocator *basicAllocator = 0);
539 /// Create a sequential pool for allocating memory blocks from an
540 /// internal buffer the initial size (in bytes) of which is indicated by
541 /// the absolute value of the specified `initialSize`. The specified
542 /// `maxBufferSize` indicates the maximum size (in bytes) allowed for
543 /// internally allocated buffers. Optionally specify an alignment
544 /// `strategy` used to align allocated memory blocks. If `strategy` is
545 /// not specified, *Natural Alignment* is used. Optionally specify a
546 /// `basicAllocator` used to supply memory. If `basicAllocator` is 0,
547 /// the currently installed default allocator is used. If an `allocate`
548 /// or `reserveCapacity` request cannot be satisfied from the current
549 /// buffer, a new buffer is allocated, the size of which is determined
550 /// by a buffer growth strategy implied by `initialSize`. If
551 /// `initialSize` is negative the buffer growth strategy used is
552 /// *Geometric Growth*; otherwise it is *Constant Growth*. (See the
553 /// component level documentation for further details.) In either case,
554 /// the new buffer will have sufficient capacity to satisfy the request.
555 /// If *Geometric Growth* is in effect, the geometric progression of
556 /// buffer sizes is capped at `maxBufferSize`. The behavior is
557 /// undefined unless `0 < maxBufferSize`, and
558 /// `|initialSize| <= maxBufferSize`. Note that `maxBufferSize` is
559 /// ignored if `initialSize > 0`. Also note that `maxBufferSize` may be
560 /// overridden by a sufficiently large value passed to `allocate` or
561 /// `reserveCapacity`.
562 SequentialPool(int initialSize,
563 int maxBufferSize,
565 Allocator *basicAllocator = 0);
566
567 SequentialPool(char *buffer,
568 int bufferSize,
569 int maxBufferSize,
570 Allocator *basicAllocator = 0);
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`. The behavior is
589 /// undefined unless `0 < maxBufferSize`, and
590 /// `|bufferSize| <= maxBufferSize`. Note that `maxBufferSize` is
591 /// ignored if `bufferSize > 0`. Also note that `maxBufferSize` may be
592 /// overridden by a sufficiently large value passed to `allocate` or
593 /// `reserveCapacity`.
594 SequentialPool(char *buffer,
595 int bufferSize,
596 int maxBufferSize,
598 Allocator *basicAllocator = 0);
599
600 /// Destroy this object and release all memory currently allocated
601 /// through this pool.
603
604 // MANIPULATORS
605
606 /// Return memory of the specified `size`. If `size` is 0, no memory is
607 /// allocated and 0 is returned. The behavior is undefined unless
608 /// `0 <= size`.
609 void *allocate(int size);
610
611 /// Return memory of at least the specified `*size` and return the
612 /// actual amount of memory allocated in `*size`. If `*size` is 0, no
613 /// memory is allocated and 0 is returned. The behavior is undefined
614 /// unless `0 <= *size`.
615 void *allocateAndExpand(int *size);
616
617 /// Return memory of at least the specified `*size` and at most the
618 /// specified `maxNumBytes`. Also return the actual amount of memory
619 /// allocated in `*size`. If `*size` is 0, no memory is allocated and 0
620 /// is returned. The behavior is undefined unless
621 /// `0 <= *size <= maxNumBytes`.
622 void *allocateAndExpand(int *size, int maxNumBytes);
623
624 /// Destroy the specified `object`. Note that this method is exactly
625 /// the same as the `deleteObjectRaw` method since no deallocation is
626 /// involved. This method exists purely for consistency across pools.
627 template <class TYPE>
628 void deleteObject(const TYPE *object);
629
630 /// Destroy the specified `object`. Note that the memory is not
631 /// deallocated because there is no `deallocate` method in a
632 /// @ref bslma_sequentialpool .
633 template <class TYPE>
634 void deleteObjectRaw(const TYPE *object);
635
636 /// Increase the amount of memory allocated at the specified `address`
637 /// from the specified `originalNumBytes` to the maximum amount easily
638 /// obtainable. Return the amount of memory available at `address`
639 /// after the expansion. The behavior is undefined unless the call to
640 /// this allocator that provided the `address` was performed with the
641 /// `originalNumBytes`. Note that this function will not expand the
642 /// memory unless there have been no allocations since the allocation
643 /// for `originalNumBytes`.
644 int expand(void *address, int originalNumBytes);
645
646 /// Increase the amount of memory allocated at the specified `address`
647 /// from the specified `originalNumBytes` to the maximum amount easily
648 /// obtainable up to the specified `maxNumBytes`. Return the amount of
649 /// memory available at `address` after the expansion. The behavior is
650 /// undefined unless the call to this allocator that provided the
651 /// `address` was performed with the `originalNumBytes` and
652 /// `originalNumBytes < maxNumBytes`. Note that this function will not
653 /// expand the memory unless there have been no allocations since the
654 /// allocation for `originalNumBytes`.
655 int expand(void *address, int originalNumBytes, int maxNumBytes);
656
657 /// Release all memory currently allocated through this pool.
658 void release();
659
660 /// Reserve sufficient memory to satisfy allocation requests for at
661 /// least the specified `numBytes` without replenishment (i.e., without
662 /// internal allocation). The behavior is undefined unless
663 /// `0 <= numBytes`.
664 void reserveCapacity(int numBytes);
665
666 /// Reduce the amount of memory allocated at the specified `address`
667 /// from the specified `originalNumBytes` to the specified
668 /// `newNumBytes`. Return the amount of memory available at `address`
669 /// after the truncation. The behavior is undefined unless the call to
670 /// this allocator that provided the `address` was performed with the
671 /// `originalNumBytes` and `newNumBytes <= originalNumBytes`. Note that
672 /// this function will not truncate the memory unless there have been no
673 /// allocations since the allocation for `originalNumBytes`.
674 int truncate(void *address, int originalNumBytes, int newNumBytes);
675};
676
677} // close package namespace
678
679
680// FREE OPERATORS
681
682// Note that the operators 'new' and 'delete' are declared outside the
683// 'BloombergLP' namespace so that they do not hide the standard placement
684// 'new' and 'delete' operators (i.e., 'void *operator new(size_t, void *)' and
685// 'void operator delete(void *)').
686//
687// Note also that only the scalar versions of operators 'new' and 'delete' are
688// provided, because overloading 'new' (and 'delete') with their array versions
689// would cause dangerous ambiguity. Consider what would have happened had we
690// overloaded the array version of operator 'new':
691//..
692// void *operator new[](std::size_t size,
693// BloombergLP::bslma::Pool& pool)
694//..
695// The user of the pool class would have expected to be able to use
696// 'new-expression':
697//..
698// new (*pool) my_Type[...];
699//..
700// The problem is that this expression returns an array that cannot be safely
701// deallocated. On the one hand there is no syntax in C++ to invoke an
702// overloaded operator delete; on the other hand the pointer returned by the
703// 'new-expression' cannot be passed to the 'deallocate' method directly
704// because the pointer is different from the one returned by the 'allocate'
705// method. The compiler offsets the value of this pointer by an extra header,
706// which the compiler uses to maintain the number of the objects in the array
707// (so that the 'delete-expression' knows how many objects it needs to
708// destroy).
709
710/// Return the memory allocated from the specified `pool`. The behavior is
711/// undefined unless `size` is the same as `objectSize` that `pool` has been
712/// constructed with. Note that an object may allocate additional memory
713/// internally, requiring the allocator to be passed in as a constructor
714/// argument:
715/// @code
716/// my_Type *newMyType(bslma::Pool *pool, bslma::Allocator *basicAllocator)
717/// {
718/// return new (*pool) my_Type(..., basicAllocator);
719/// }
720/// @endcode
721/// Note also that the analogous version of operator `delete` should not be
722/// called directly. Instead, this component provides a static template
723/// member function `deleteObject` parameterized by `TYPE` that performs the
724/// following:
725/// @code
726/// void deleteMyType(bslma::Pool *pool, my_Type *t)
727/// {
728/// t->~my_Type();
729/// pool->deallocate(t);
730/// }
731/// @endcode
732inline
733void *operator new(std::size_t size, BloombergLP::bslma::SequentialPool& pool);
734
735/// Use the specified `pool` to deallocate the memory at the specified
736/// `address`. The behavior is undefined unless `address` was allocated
737/// using `pool` and has not already been deallocated. This operator is
738/// supplied solely to allow the compiler to arrange for it to be called in
739/// case of an exception.
740inline
741void operator delete(void *address, BloombergLP::bslma::SequentialPool& pool);
742
743// ============================================================================
744// INLINE DEFINITIONS
745// ============================================================================
746
747
748namespace bslma {
749
750 // --------------
751 // SequentialPool
752 // --------------
753
754// CREATORS
755inline
759
760// MANIPULATORS
761template <class TYPE>
762inline
763void SequentialPool::deleteObjectRaw(const TYPE *object)
764{
765 if (0 != object) {
766#if defined(BSLS_PLATFORM_CMP_SUN) && BSLS_PLATFORM_CMP_VERSION < 0x5130
767 const_cast<TYPE *>(object)->~TYPE();
768#else
769 object->~TYPE();
770#endif
771 }
772}
773
774template <class TYPE>
775inline
776void SequentialPool::deleteObject(const TYPE *object)
777{
778 deleteObjectRaw(object);
779}
780
781} // close package namespace
782
783#ifndef BDE_OPENSOURCE_PUBLICATION // BACKWARD_COMPATIBILITY
784// ============================================================================
785// BACKWARD COMPATIBILITY
786// ============================================================================
787
788/// This alias is defined for backward compatibility.
790#endif // BDE_OPENSOURCE_PUBLICATION -- BACKWARD_COMPATIBILITY
791
792
793
794// FREE OPERATORS
795
796inline
797void *operator new(std::size_t size, BloombergLP::bslma::SequentialPool& pool)
798{
799 return pool.allocate(static_cast<int>(size));
800}
801
802inline
803void operator delete(void *, BloombergLP::bslma::SequentialPool&)
804{
805 // NOTE: there is no deallocation from this allocation mechanism.
806}
807
808#endif
809
810// ----------------------------------------------------------------------------
811// Copyright 2013 Bloomberg Finance L.P.
812//
813// Licensed under the Apache License, Version 2.0 (the "License");
814// you may not use this file except in compliance with the License.
815// You may obtain a copy of the License at
816//
817// http://www.apache.org/licenses/LICENSE-2.0
818//
819// Unless required by applicable law or agreed to in writing, software
820// distributed under the License is distributed on an "AS IS" BASIS,
821// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
822// See the License for the specific language governing permissions and
823// limitations under the License.
824// ----------------------------- END-OF-FILE ----------------------------------
825
826/** @} */
827/** @} */
828/** @} */
Definition bslma_allocator.h:457
AlignmentStrategy
Types of alignment strategy to allocate memory.
Definition bslma_bufferallocator.h:274
Definition bslma_infrequentdeleteblocklist.h:216
Definition bslma_sequentialpool.h:440
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:763
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:756
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:776
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:789
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
Definition balxml_encoderoptions.h:68