BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bdlma_bufferedsequentialpool.h
Go to the documentation of this file.
1/// @file bdlma_bufferedsequentialpool.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bdlma_bufferedsequentialpool.h -*-C++-*-
8#ifndef INCLUDED_BDLMA_BUFFEREDSEQUENTIALPOOL
9#define INCLUDED_BDLMA_BUFFEREDSEQUENTIALPOOL
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bdlma_bufferedsequentialpool bdlma_bufferedsequentialpool
15/// @brief Provide sequential memory using an external buffer and a fallback.
16/// @addtogroup bdl
17/// @{
18/// @addtogroup bdlma
19/// @{
20/// @addtogroup bdlma_bufferedsequentialpool
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bdlma_bufferedsequentialpool-purpose"> Purpose</a>
25/// * <a href="#bdlma_bufferedsequentialpool-classes"> Classes </a>
26/// * <a href="#bdlma_bufferedsequentialpool-description"> Description </a>
27/// * <a href="#bdlma_bufferedsequentialpool-optional-maxbuffersize-parameter"> Optional maxBufferSize Parameter </a>
28/// * <a href="#bdlma_bufferedsequentialpool-warning"> Warning </a>
29/// * <a href="#bdlma_bufferedsequentialpool-usage"> Usage </a>
30/// * <a href="#bdlma_bufferedsequentialpool-example-1-using-bdlma-bufferedsequentialpool-for-efficient-allocations"> Example 1: Using bdlma::BufferedSequentialPool for Efficient Allocations </a>
31/// * <a href="#bdlma_bufferedsequentialpool-example-2-implementing-an-allocator-using-bdlma-bufferedsequentialpool"> Example 2: Implementing an Allocator Using bdlma::BufferedSequentialPool </a>
32///
33/// # Purpose {#bdlma_bufferedsequentialpool-purpose}
34/// Provide sequential memory using an external buffer and a fallback.
35///
36/// # Classes {#bdlma_bufferedsequentialpool-classes}
37///
38/// - bdlma::BufferedSequentialPool: pool using an external buffer and a fallback
39///
40/// @see bdlma_buffermanager, bdlma_sequentialpool
41///
42/// # Description {#bdlma_bufferedsequentialpool-description}
43/// This component provides a maximally efficient sequential memory
44/// pool, `bdlma::BufferedSequentialPool`, that dispenses heterogeneous memory
45/// blocks (of varying, user-specified sizes) from an external buffer. If an
46/// allocation request exceeds the remaining free memory space in the external
47/// buffer, the pool will fall back to a sequence of dynamically allocated
48/// buffers. Users can optionally specify a growth strategy at construction
49/// that governs the growth rate of the dynamically-allocated buffers. If no
50/// growth strategy is specified at construction, geometric growth is used.
51/// Users can also optionally specify an alignment strategy at construction that
52/// governs the alignment of allocated memory blocks. If no alignment strategy
53/// is specified, natural alignment is used. The `release` method releases all
54/// memory allocated through the pool, as does the destructor. The `rewind`
55/// method releases all memory allocated through the pool and returns to the
56/// underlying allocator *only* memory that was allocated outside of the typical
57/// internal buffer growth of the pool (i.e., large blocks). Note that
58/// individually allocated memory blocks cannot be separately deallocated.
59///
60/// A `bdlma::BufferedSequentialPool` is typically used when users have a
61/// reasonable estimation of the amount of memory needed. This amount of memory
62/// would typically be created directly on the program stack, and used as the
63/// initial external buffer of the pool for fast memory allocation. While the
64/// buffer has sufficient capacity, memory allocations using the pool will not
65/// trigger *any* dynamic memory allocation, will have optimal locality of
66/// reference, and will not require deallocation upon destruction.
67///
68/// Once the external buffer is exhausted, subsequent allocation requests
69/// require dynamic memory allocation, and the performance of the pool degrades.
70///
71/// ### Optional maxBufferSize Parameter {#bdlma_bufferedsequentialpool-optional-maxbuffersize-parameter}
72///
73///
74/// An optional `maxBufferSize` parameter can be supplied at construction to
75/// specify the maximum size (in bytes) of the dynamically-allocated buffers for
76/// geometric growth. Once the internal buffer grows up to the `maxBufferSize`,
77/// further requests that exceed this size will be served by a separate memory
78/// block instead of the internal buffer. The behavior is undefined unless
79/// `size <= maxBufferSize`, where `size` is the extent (in bytes) of the
80/// external buffer supplied at construction.
81///
82/// ## Warning {#bdlma_bufferedsequentialpool-warning}
83///
84///
85/// Note that, even when a buffer having `n` bytes of memory is supplied at
86/// construction, it does *not* mean that `n` bytes of memory are available
87/// before dynamic memory allocation is triggered. This is due to memory
88/// alignment requirements. If the buffer supplied is not aligned, the first
89/// call to the `allocate` method may automatically skip one or more bytes such
90/// that the memory allocated is properly aligned. The number of bytes that are
91/// wasted depends on whether natural alignment, maximum alignment, or 1-byte
92/// alignment is used (see @ref bsls_alignment for more details).
93///
94/// ## Usage {#bdlma_bufferedsequentialpool-usage}
95///
96///
97/// This section illustrates intended use of this component.
98///
99/// ### Example 1: Using bdlma::BufferedSequentialPool for Efficient Allocations {#bdlma_bufferedsequentialpool-example-1-using-bdlma-bufferedsequentialpool-for-efficient-allocations}
100///
101///
102/// Suppose we define a container class, `my_BufferedIntDoubleArray`, that holds
103/// both `int` and `double` values. The class can be implemented using two
104/// parallel arrays: one storing the type information, and the other storing
105/// pointers to the `int` and `double` values. Furthermore, if we can
106/// approximate the amount of memory needed, we can use a
107/// `bdlma::BufferedSequentialPool` for memory allocation for maximum
108/// efficiency:
109/// @code
110/// // my_bufferedintdoublearray.h
111///
112/// class my_BufferedIntDoubleArray {
113/// // This class implements an efficient container for an array that
114/// // stores both 'int' and 'double' values.
115///
116/// // DATA
117/// char *d_typeArray_p; // array indicating the type of corresponding
118/// // values stored in 'd_valueArray_p'
119///
120/// void **d_valueArray_p; // array of pointers to the values stored
121///
122/// int d_length; // number of values stored
123///
124/// int d_capacity; // physical capacity of the type and value
125/// // arrays
126///
127/// bdlma::BufferedSequentialPool
128/// d_pool; // buffered sequential memory pool used to
129/// // supply memory
130///
131/// private:
132/// // NOT IMPLEMENTED
133/// my_BufferedIntDoubleArray(const my_BufferedIntDoubleArray&);
134///
135/// private:
136/// // PRIVATE MANIPULATORS
137/// void increaseCapacity();
138/// // Increase the capacity of the internal arrays used to store
139/// // elements added to this array by at least one element.
140///
141/// public:
142/// // TYPES
143/// enum Type { k_MY_INT, k_MY_DOUBLE };
144///
145/// // CREATORS
146/// my_BufferedIntDoubleArray(char *buffer,
147/// int size,
148/// bslma::Allocator *basicAllocator = 0);
149/// // Create a fast 'int'-'double' array that initially allocates
150/// // memory sequentially from the specified 'buffer' having the
151/// // specified 'size' (in bytes). Optionally specify a
152/// // 'basicAllocator' used to supply memory if 'buffer' capacity is
153/// // exceeded. If 'basicAllocator' is 0, the currently installed
154/// // default allocator is used.
155///
156/// ~my_BufferedIntDoubleArray();
157/// // Destroy this array and all elements held by it.
158///
159/// // ...
160///
161/// // MANIPULATORS
162/// void appendInt(int value);
163/// // Append the specified 'int' 'value' to this array.
164///
165/// void appendDouble(double value);
166/// // Append the specified 'double' 'value' to this array.
167///
168/// void removeAll();
169/// // Remove all elements from this array.
170///
171/// // ...
172/// };
173/// @endcode
174/// The use of a buffered sequential pool and the `release` method allows the
175/// `removeAll` method to quickly deallocate memory of all elements:
176/// @code
177/// // MANIPULATORS
178/// inline
179/// void my_BufferedIntDoubleArray::removeAll()
180/// {
181/// d_pool.release(); // *very* efficient if 'd_pool' has not exhausted
182/// // the buffer supplied at construction
183///
184/// d_length = 0;
185/// }
186/// @endcode
187/// The buffered sequential pool optimizes the allocation of memory by using a
188/// buffer supplied at construction. As described in the "DESCRIPTION" section,
189/// the need for *all* dynamic memory allocations are eliminated provided that
190/// the buffer is not exhausted. The pool provides maximal memory allocation
191/// efficiency:
192/// @code
193/// // my_bufferedintdoublearray.cpp
194///
195/// enum { k_INITIAL_SIZE = 1 };
196///
197/// // PRIVATE MANIPULATORS
198/// void my_BufferedIntDoubleArray::increaseCapacity()
199/// {
200/// // Implementation elided.
201/// // ...
202/// }
203///
204/// // CREATORS
205/// my_BufferedIntDoubleArray::my_BufferedIntDoubleArray(
206/// char *buffer,
207/// int size,
208/// bslma::Allocator *basicAllocator)
209/// : d_length(0)
210/// , d_capacity(k_INITIAL_SIZE)
211/// , d_pool(buffer, size, basicAllocator)
212/// {
213/// d_typeArray_p = static_cast<char *>(
214/// d_pool.allocate(d_capacity * sizeof *d_typeArray_p));
215/// d_valueArray_p = static_cast<void **>(
216/// d_pool.allocate(d_capacity * sizeof *d_valueArray_p));
217/// }
218/// @endcode
219/// Note that in the destructor, all outstanding memory blocks are deallocated
220/// automatically when `d_pool` is destroyed:
221/// @code
222/// my_BufferedIntDoubleArray::~my_BufferedIntDoubleArray()
223/// {
224/// assert(0 <= d_length);
225/// assert(0 <= d_capacity);
226/// assert(d_length <= d_capacity);
227/// }
228///
229/// // MANIPULATORS
230/// void my_BufferedIntDoubleArray::appendDouble(double value)
231/// {
232/// if (d_length >= d_capacity) {
233/// increaseCapacity();
234/// }
235///
236/// double *item = static_cast<double *>(d_pool.allocate(sizeof *item));
237/// *item = value;
238///
239/// d_typeArray_p[d_length] = static_cast<char>(k_MY_DOUBLE);
240/// d_valueArray_p[d_length] = item;
241///
242/// ++d_length;
243/// }
244///
245/// void my_BufferedIntDoubleArray::appendInt(int value)
246/// {
247/// if (d_length >= d_capacity) {
248/// increaseCapacity();
249/// }
250///
251/// int *item = static_cast<int *>(d_pool.allocate(sizeof *item));
252/// *item = value;
253///
254/// d_typeArray_p[d_length] = static_cast<char>(k_MY_INT);
255/// d_valueArray_p[d_length] = item;
256///
257/// ++d_length;
258/// }
259/// @endcode
260///
261/// ### Example 2: Implementing an Allocator Using bdlma::BufferedSequentialPool {#bdlma_bufferedsequentialpool-example-2-implementing-an-allocator-using-bdlma-bufferedsequentialpool}
262///
263///
264/// `bslma::Allocator` is used throughout the interfaces of BDE components.
265/// Suppose we would like to create a fast allocator, `my_FastAllocator`, that
266/// allocates memory from a buffer in a similar fashion to
267/// `bdlma::BufferedSequentialPool`. `bdlma::BufferedSequentialPool` can be
268/// used directly to implement such an allocator.
269///
270/// Note that the documentation for this class is simplified for this usage
271/// example. Please see @ref bdlma_bufferedsequentialallocator for full
272/// documentation of a similar class.
273/// @code
274/// class my_FastAllocator : public bslma::Allocator {
275/// // This class implements the 'bslma::Allocator' protocol to provide a
276/// // fast allocator of heterogeneous blocks of memory (of varying,
277/// // user-specified sizes) from an external buffer whose address and size
278/// // are supplied at construction.
279///
280/// // DATA
281/// bdlma::BufferedSequentialPool d_pool; // memory manager for allocated
282/// // memory blocks
283///
284/// // CREATORS
285/// my_FastAllocator(char *buffer,
286/// int size,
287/// bslma::Allocator *basicAllocator = 0);
288/// // Create an allocator for allocating memory blocks from the
289/// // specified external 'buffer' of the specified 'size' (in bytes).
290/// // Optionally specify a 'basicAllocator' used to supply memory
291/// // should the capacity of 'buffer' be exhausted. If
292/// // 'basicAllocator' is 0, the currently installed default allocator
293/// // is used.
294///
295/// ~my_FastAllocator();
296/// // Destroy this allocator. All memory allocated from this
297/// // allocator is released.
298///
299/// // MANIPULATORS
300/// virtual void *allocate(size_type size);
301/// // Return the address of a contiguous block of memory of the
302/// // specified 'size' (in bytes).
303///
304/// virtual void deallocate(void *address);
305/// // This method has no effect on the memory block at the specified
306/// // 'address' as all memory allocated by this allocator is managed.
307/// // The behavior is undefined unless 'address' was allocated by this
308/// // allocator, and has not already been deallocated.
309/// };
310///
311/// // CREATORS
312/// inline
313/// my_FastAllocator::my_FastAllocator(char *buffer,
314/// int size,
315/// bslma::Allocator *basicAllocator)
316/// : d_pool(buffer, size, basicAllocator)
317/// {
318/// }
319///
320/// inline
321/// my_FastAllocator::~my_FastAllocator()
322/// {
323/// d_pool.release();
324/// }
325///
326/// // MANIPULATORS
327/// inline
328/// void *my_FastAllocator::allocate(size_type size)
329/// {
330/// return d_pool.allocate(size);
331/// }
332///
333/// inline
334/// void my_FastAllocator::deallocate(void *)
335/// {
336/// }
337/// @endcode
338/// @}
339/** @} */
340/** @} */
341
342/** @addtogroup bdl
343 * @{
344 */
345/** @addtogroup bdlma
346 * @{
347 */
348/** @addtogroup bdlma_bufferedsequentialpool
349 * @{
350 */
351
352#include <bdlscm_version.h>
353
354#include <bdlma_buffermanager.h>
355#include <bdlma_sequentialpool.h>
356
357#include <bslma_allocator.h>
358
359#include <bsls_alignment.h>
360#include <bsls_assert.h>
361#include <bsls_blockgrowth.h>
362#include <bsls_platform.h>
363#include <bsls_performancehint.h>
364#include <bsls_types.h>
365
366#include <bsl_cstddef.h>
367
368
369namespace bdlma {
370
371 // ============================
372 // class BufferedSequentialPool
373 // ============================
374
375/// This class implements a fast memory pool that efficiently dispenses
376/// heterogeneous blocks of memory (of varying, user-specified sizes) from
377/// an external buffer whose address and size (in bytes) are supplied at
378/// construction. If an allocation request exceeds the remaining free
379/// memory space in the external buffer, memory will be supplied by an
380/// (optional) allocator supplied also at construction; if no allocator is
381/// supplied, the currently installed default allocator will be used. This
382/// class is *exception* *neutral*: If memory cannot be allocated, the
383/// behavior is defined by the (optional) allocator supplied at
384/// construction. Note that in no case will the buffered sequential pool
385/// attempt to deallocate the external buffer.
386///
387/// See @ref bdlma_bufferedsequentialpool
389
390 // DATA
391 BufferManager d_bufferManager; // memory manager for current
392 // buffer
393
394 bsls::Types::size_type d_maxBufferSize; // max buffer size parameter to
395 // be passed to the sequential
396 // allocator upon construction
397
398 unsigned char d_growthStrategy; // the growth strategy to be
399 // passed to the sequential
400 // pool
401
402 bool d_sequentialPoolIsCreated;
403 // indicates whether the
404 // sequential pool has been
405 // created yet
406
407 union {
408 bslma::Allocator *d_allocator_p; // allocator we were
409 // constructed with if the
410 // sequential pool hasn't been
411 // created
412
413 SequentialPool *d_pool_p; // memory manager for
414 }; // allocations not from the
415 // buffer, if the sequential
416 // pool has been created
417
418 private:
419 // NOT IMPLEMENTED
422
423 private:
424 // PRIVATE MANIPULATORS
425
426 /// Allocate and construct the sequential pool, using a block size of
427 /// `bufferManager.bufferSize()`. Use the specified
428 /// `currentAllocationSize` to determine if the current allocation
429 /// attempt will fit in the first block, and thus what boolean value to
430 /// pass to the sequental pool's `allocateInitialBuffer` argument.
431 void createSequentialPool(bsls::Types::size_type currentAllocationSize);
432
433 // PRIVATE ACCESSORS
434
435 /// Return the alignment strategy to be used by the sequential pool.
436 bsls::Alignment::Strategy alignmentStrategy() const;
437
438 /// Return the growth strategy to be used by the sequential pool.
439 bsls::BlockGrowth::Strategy growthStrategy() const;
440
441 public:
442 // CREATORS
443
446 bslma::Allocator *basicAllocator = 0);
449 bsls::BlockGrowth::Strategy growthStrategy,
450 bslma::Allocator *basicAllocator = 0);
453 bsls::Alignment::Strategy alignmentStrategy,
454 bslma::Allocator *basicAllocator = 0);
455 /// Create a buffered sequential pool for allocating memory blocks from
456 /// the specified external `buffer` having the specified `size` (in
457 /// bytes), or from an internal buffer (after the external `buffer` is
458 /// exhausted). Optionally specify a `growthStrategy` used to control
459 /// buffer growth. If a `growthStrategy` is not specified, geometric
460 /// growth is used. Optionally specify an `alignmentStrategy` used to
461 /// align allocated memory blocks. If an `alignmentStrategy` is not
462 /// specified, natural alignment is used. Optionally specify a
463 /// `basicAllocator` used to supply memory should the capacity of
464 /// `buffer` be exhausted. If `basicAllocator` is 0, the currently
465 /// installed default allocator is used. The behavior is undefined
466 /// unless `0 < size`, and `buffer` has at least `size` bytes. Note
467 /// that, due to alignment effects, it is possible that not all `size`
468 /// bytes of memory in `buffer` can be used for allocation. Also note
469 /// that no limit is imposed on the size of the internal buffers when
470 /// geometric growth is used. Also note that when constant growth is
471 /// used, the size of the internal buffers will always be the same as
472 /// `size`.
475 bsls::BlockGrowth::Strategy growthStrategy,
476 bsls::Alignment::Strategy alignmentStrategy,
477 bslma::Allocator *basicAllocator = 0);
478
481 bsls::Types::size_type maxBufferSize,
482 bslma::Allocator *basicAllocator = 0);
485 bsls::Types::size_type maxBufferSize,
486 bsls::BlockGrowth::Strategy growthStrategy,
487 bslma::Allocator *basicAllocator = 0);
490 bsls::Types::size_type maxBufferSize,
491 bsls::Alignment::Strategy alignmentStrategy,
492 bslma::Allocator *basicAllocator = 0);
493 /// Create a buffered sequential pool for allocating memory blocks from
494 /// the specified external `buffer` having the specified `size` (in
495 /// bytes), or from an internal buffer (after the external `buffer` is
496 /// exhausted) where the buffer growth is limited to the specified
497 /// `maxBufferSize` (in bytes). Optionally specify a `growthStrategy`
498 /// used to control buffer growth. If a `growthStrategy` is not
499 /// specified, geometric growth is used. Optionally specify an
500 /// `alignmentStrategy` used to align allocated memory blocks. If an
501 /// `alignmentStrategy` is not specified, natural alignment is used.
502 /// Optionally specify a `basicAllocator` used to supply memory should
503 /// the capacity of `buffer` be exhausted. If `basicAllocator` is 0,
504 /// the currently installed default allocator is used. The behavior is
505 /// undefined unless `0 < size`, `size <= maxBufferSize`, and `buffer`
506 /// has at least `size` bytes. Note that, due to alignment effects, it
507 /// is possible that not all `size` bytes of memory in `buffer` can be
508 /// used for allocation. Also note that when constant growth is used,
509 /// the size of the internal buffers will always be the same as `size`.
512 bsls::Types::size_type maxBufferSize,
513 bsls::BlockGrowth::Strategy growthStrategy,
514 bsls::Alignment::Strategy alignmentStrategy,
515 bslma::Allocator *basicAllocator = 0);
516
517 /// Destroy this buffered sequential pool. All memory allocated from
518 /// this pool is released.
520
521 // MANIPULATORS
522
523 /// Return the address of a contiguous block of memory of the specified
524 /// `size` (in bytes) according to the alignment strategy specified at
525 /// construction. If `size` is 0, no memory is allocated and 0 is
526 /// returned. If the allocation request exceeds the remaining free
527 /// memory space in the external buffer supplied at construction, use
528 /// memory obtained from the allocator supplied at construction.
530
531 /// Destroy the specified `object`. Note that this method has the same
532 /// effect as the `deleteObjectRaw` method (since no deallocation is
533 /// involved), and exists for consistency across memory pools.
534 template <class TYPE>
535 void deleteObject(const TYPE *object);
536
537 /// Destroy the specified `object`. Note that memory associated with
538 /// `object` is not deallocated because there is no `deallocate` method
539 /// in `BufferedSequentialPool`.
540 template <class TYPE>
541 void deleteObjectRaw(const TYPE *object);
542
543 /// Release all memory allocated through this pool and return to the
544 /// underlying allocator *all* memory except the external buffer
545 /// supplied at construction. The pool is reset to its
546 /// default-constructed state, making the memory from the entire
547 /// external buffer supplied at construction available for subsequent
548 /// allocations, retaining the alignment and growth strategies, and the
549 /// initial and maximum buffer sizes in effect following construction.
550 /// The effect of subsequently - to this invokation of `release` - using
551 /// a pointer obtained from this object prior to this call to `release`
552 /// is undefined.
553 void release();
554
555 /// Release all memory allocated through this pool and return to the
556 /// underlying allocator *only* memory that was allocated outside of the
557 /// typical internal buffer growth of this pool (i.e., large blocks).
558 /// All retained memory will be used to satisfy subsequent allocations.
559 /// The effect of subsequently - to this invokation of `rewind` - using
560 /// a pointer obtained from this object prior to this call to `rewind`
561 /// is undefined.
562 void rewind();
563
564 // ACCESSORS
565
566 /// Return the allocator used by this object to allocate memory. Note
567 /// that this allocator can not be used to deallocate memory allocated
568 /// through this pool.
570};
571
572} // close package namespace
573
574
575// Note that the 'new' and 'delete' operators are declared outside the
576// 'BloombergLP' namespace so that they do not hide the standard placement
577// 'new' and 'delete' operators (i.e.,
578// 'void *operator new(bsl::size_t, void *)' and
579// 'void operator delete(void *)').
580//
581// Also note that only the scalar versions of operators 'new' and 'delete' are
582// provided, because overloading 'new' (and 'delete') with their array versions
583// would cause dangerous ambiguity. Consider what would have happened had we
584// overloaded the array version of 'operator new':
585//..
586// void *operator new[](bsl::size_t size,
587// BloombergLP::bdlma::BufferedSequentialPool& pool);
588//..
589// The user of the pool class would have expected to be able to use operator
590// 'new' as follows:
591//..
592// new (*pool) my_Type[...];
593//..
594// The problem is that this expression returns an array that cannot be safely
595// deallocated. On the one hand, there is no syntax in C++ to invoke an
596// overloaded 'operator delete'; on the other hand, the pointer returned by
597// 'operator new' cannot be passed to the 'deallocate' method directly because
598// the pointer is different from the one returned by the 'allocate' method.
599// The compiler offsets the value of this pointer by a header, which is used to
600// maintain the number of objects in the array (so that the 'operator delete'
601// can destroy the right number of objects).
602
603// FREE OPERATORS
604
605/// Return a block of memory of the specified `size` (in bytes) allocated
606/// from the specified `pool`. Note that an object may allocate additional
607/// memory internally, requiring the allocator to be passed in as a
608/// constructor argument:
609/// @code
610/// my_Type *newMyType(bdlma::BufferedSequentialPool *pool,
611/// bslma::Allocator *basicAllocator)
612/// {
613/// return new (*pool) my_Type(..., basicAllocator);
614/// }
615/// @endcode
616/// Also note that the analogous version of `operator delete` should not be
617/// called directly. Instead, this component provides a static template
618/// member function, `deleteObject`, parameterized by `TYPE` that performs
619/// the following:
620/// @code
621/// void deleteMyType(bdlma::BufferedSequentialPool *pool, my_Type *t)
622/// {
623/// t->~my_Type();
624/// }
625/// @endcode
626void *operator new(bsl::size_t size,
627 BloombergLP::bdlma::BufferedSequentialPool& pool);
628
629/// Use the specified `pool` to deallocate the memory at the specified
630/// `address`. The behavior is undefined unless `address` was allocated
631/// using `pool` and has not already been deallocated. This operator is
632/// supplied solely to allow the compiler to arrange for it to be called in
633/// case of an exception.
634void operator delete(void *address,
635 BloombergLP::bdlma::BufferedSequentialPool& pool);
636
637// ============================================================================
638// INLINE DEFINITIONS
639// ============================================================================
640
641
642namespace bdlma {
643
644 // ----------------------------
645 // class BufferedSequentialPool
646 // ----------------------------
647
648// PRIVATE ACCESSORS
649inline
650bsls::Alignment::Strategy BufferedSequentialPool::alignmentStrategy() const
651{
652 return d_bufferManager.alignmentStrategy();
653}
654
655inline
656bsls::BlockGrowth::Strategy BufferedSequentialPool::growthStrategy() const
657{
658 return static_cast<bsls::BlockGrowth::Strategy>(d_growthStrategy);
659}
660
661// CREATORS
662inline
664{
665 // 'd_bufferManager' doesn't need to be released, it will destroy itself
666 // just fine.
667
668 if (d_sequentialPoolIsCreated) {
670 }
671}
672
673// MANIPULATORS
674inline
676{
679 return 0; // RETURN
680 }
681
682 void *result = d_bufferManager.allocate(size);
684 return result; // RETURN
685 }
686
687 if (false == d_sequentialPoolIsCreated) {
688 this->createSequentialPool(size);
689 }
690
691 return d_pool_p->allocate(size);
692}
693
694template <class TYPE>
695inline
697{
698 this->deleteObjectRaw(object);
699}
700
701template <class TYPE>
702inline
704{
705 if (0 != object) {
706#ifndef BSLS_PLATFORM_CMP_SUN
707 object->~TYPE();
708#else
709 const_cast<TYPE *>(object)->~TYPE();
710#endif
711 }
712}
713
714inline
716{
717 d_bufferManager.release(); // Reset the internal cursor in the current
718 // block.
719
720 if (d_sequentialPoolIsCreated) {
721 // Note that 'd_pool_p' and 'd_allocator_p' fit in the same footprint
722 // in an anonymous union.
723
724 bslma::Allocator *alloc_p = d_pool_p->allocator();
725 alloc_p->deleteObjectRaw(d_pool_p);
726 d_allocator_p = alloc_p;
727
728 d_sequentialPoolIsCreated = false;
729 }
730}
731
732inline
734
735{
736 d_bufferManager.release(); // Reset the internal cursor in the current
737 // block.
738
739 if (d_sequentialPoolIsCreated) {
740 d_pool_p->rewind();
741 }
742}
743
744// ACCESSORS
745inline
747{
748 return d_sequentialPoolIsCreated ? d_pool_p->allocator()
750}
751
752} // close package namespace
753
754
755// FREE OPERATORS
756inline
757void *operator new(bsl::size_t size,
758 BloombergLP::bdlma::BufferedSequentialPool& pool)
759{
760 return pool.allocate(size);
761}
762
763inline
764void operator delete(void *, BloombergLP::bdlma::BufferedSequentialPool&)
765{
766 // NOTE: there is no deallocation from this allocation mechanism.
767}
768
769#endif
770
771// ----------------------------------------------------------------------------
772// Copyright 2016 Bloomberg Finance L.P.
773//
774// Licensed under the Apache License, Version 2.0 (the "License");
775// you may not use this file except in compliance with the License.
776// You may obtain a copy of the License at
777//
778// http://www.apache.org/licenses/LICENSE-2.0
779//
780// Unless required by applicable law or agreed to in writing, software
781// distributed under the License is distributed on an "AS IS" BASIS,
782// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
783// See the License for the specific language governing permissions and
784// limitations under the License.
785// ----------------------------- END-OF-FILE ----------------------------------
786
787/** @} */
788/** @} */
789/** @} */
Definition bdlma_buffermanager.h:307
void release()
Definition bdlma_buffermanager.h:597
bsls::Alignment::Strategy alignmentStrategy() const
Definition bdlma_buffermanager.h:612
void * allocate(bsls::Types::size_type size)
Definition bdlma_buffermanager.h:523
Definition bdlma_bufferedsequentialpool.h:388
~BufferedSequentialPool()
Definition bdlma_bufferedsequentialpool.h:663
BufferedSequentialPool(char *buffer, bsls::Types::size_type size, bsls::Types::size_type maxBufferSize, bsls::BlockGrowth::Strategy growthStrategy, bslma::Allocator *basicAllocator=0)
void deleteObjectRaw(const TYPE *object)
Definition bdlma_bufferedsequentialpool.h:703
BufferedSequentialPool(char *buffer, bsls::Types::size_type size, bsls::BlockGrowth::Strategy growthStrategy, bslma::Allocator *basicAllocator=0)
void deleteObject(const TYPE *object)
Definition bdlma_bufferedsequentialpool.h:696
bslma::Allocator * d_allocator_p
Definition bdlma_bufferedsequentialpool.h:408
BufferedSequentialPool(char *buffer, bsls::Types::size_type size, bsls::Types::size_type maxBufferSize, bslma::Allocator *basicAllocator=0)
BufferedSequentialPool(char *buffer, bsls::Types::size_type size, bsls::BlockGrowth::Strategy growthStrategy, bsls::Alignment::Strategy alignmentStrategy, bslma::Allocator *basicAllocator=0)
BufferedSequentialPool(char *buffer, bsls::Types::size_type size, bsls::Types::size_type maxBufferSize, bsls::Alignment::Strategy alignmentStrategy, bslma::Allocator *basicAllocator=0)
BufferedSequentialPool(char *buffer, bsls::Types::size_type size, bslma::Allocator *basicAllocator=0)
SequentialPool * d_pool_p
Definition bdlma_bufferedsequentialpool.h:413
bslma::Allocator * allocator() const
Definition bdlma_bufferedsequentialpool.h:746
void release()
Definition bdlma_bufferedsequentialpool.h:715
void rewind()
Definition bdlma_bufferedsequentialpool.h:733
BufferedSequentialPool(char *buffer, bsls::Types::size_type size, bsls::Types::size_type maxBufferSize, bsls::BlockGrowth::Strategy growthStrategy, bsls::Alignment::Strategy alignmentStrategy, bslma::Allocator *basicAllocator=0)
BufferedSequentialPool(char *buffer, bsls::Types::size_type size, bsls::Alignment::Strategy alignmentStrategy, bslma::Allocator *basicAllocator=0)
void * allocate(bsls::Types::size_type size)
Definition bdlma_bufferedsequentialpool.h:675
Definition bdlma_sequentialpool.h:378
bslma::Allocator * allocator() const
Definition bdlma_sequentialpool.h:814
void * allocate(bsls::Types::size_type size)
Definition bdlma_sequentialpool.h:756
Definition bslma_allocator.h:457
void deleteObjectRaw(const TYPE *object)
Definition bslma_allocator.h:694
virtual void * allocate(size_type size)=0
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
#define BSLS_PERFORMANCEHINT_PREDICT_LIKELY(expr)
Definition bsls_performancehint.h:451
#define BSLS_PERFORMANCEHINT_UNLIKELY_HINT
Definition bsls_performancehint.h:484
#define BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(expr)
Definition bsls_performancehint.h:452
Definition bdlma_alignedallocator.h:276
Strategy
Types of alignment strategy.
Definition bsls_alignment.h:239
Strategy
Definition bsls_blockgrowth.h:169
std::size_t size_type
Definition bsls_types.h:124