BDE 4.39.x 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/// /// This class implements an efficient container for an array that
113/// /// stores both `int` and `double` values.
114/// class my_BufferedIntDoubleArray {
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///
138/// /// Increase the capacity of the internal arrays used to store
139/// /// elements added to this array by at least one element.
140/// void increaseCapacity();
141///
142/// public:
143/// // TYPES
144/// enum Type { k_MY_INT, k_MY_DOUBLE };
145///
146/// // CREATORS
147///
148/// /// Create a fast `int`-`double` array that initially allocates
149/// /// memory sequentially from the specified `buffer` having the
150/// /// specified `size` (in bytes). Optionally specify a
151/// /// `basicAllocator` used to supply memory if `buffer` capacity is
152/// /// exceeded. If `basicAllocator` is 0, the currently installed
153/// /// default allocator is used.
154/// my_BufferedIntDoubleArray(char *buffer,
155/// int size,
156/// bslma::Allocator *basicAllocator = 0);
157///
158/// /// Destroy this array and all elements held by it.
159/// ~my_BufferedIntDoubleArray();
160///
161/// // ...
162///
163/// // MANIPULATORS
164///
165/// /// Append the specified `int` `value` to this array.
166/// void appendInt(int value);
167///
168/// /// Append the specified `double` `value` to this array.
169/// void appendDouble(double value);
170///
171/// /// Remove all elements from this array.
172/// void removeAll();
173///
174/// // ...
175/// };
176/// @endcode
177/// The use of a buffered sequential pool and the `release` method allows the
178/// `removeAll` method to quickly deallocate memory of all elements:
179/// @code
180/// // MANIPULATORS
181/// inline
182/// void my_BufferedIntDoubleArray::removeAll()
183/// {
184/// d_pool.release(); // *very* efficient if 'd_pool' has not exhausted
185/// // the buffer supplied at construction
186///
187/// d_length = 0;
188/// }
189/// @endcode
190/// The buffered sequential pool optimizes the allocation of memory by using a
191/// buffer supplied at construction. As described in the "DESCRIPTION" section,
192/// the need for *all* dynamic memory allocations are eliminated provided that
193/// the buffer is not exhausted. The pool provides maximal memory allocation
194/// efficiency:
195/// @code
196/// // my_bufferedintdoublearray.cpp
197///
198/// enum { k_INITIAL_SIZE = 1 };
199///
200/// // PRIVATE MANIPULATORS
201/// void my_BufferedIntDoubleArray::increaseCapacity()
202/// {
203/// // Implementation elided.
204/// // ...
205/// }
206///
207/// // CREATORS
208/// my_BufferedIntDoubleArray::my_BufferedIntDoubleArray(
209/// char *buffer,
210/// int size,
211/// bslma::Allocator *basicAllocator)
212/// : d_length(0)
213/// , d_capacity(k_INITIAL_SIZE)
214/// , d_pool(buffer, size, basicAllocator)
215/// {
216/// d_typeArray_p = static_cast<char *>(
217/// d_pool.allocate(d_capacity * sizeof *d_typeArray_p));
218/// d_valueArray_p = static_cast<void **>(
219/// d_pool.allocate(d_capacity * sizeof *d_valueArray_p));
220/// }
221/// @endcode
222/// Note that in the destructor, all outstanding memory blocks are deallocated
223/// automatically when `d_pool` is destroyed:
224/// @code
225/// my_BufferedIntDoubleArray::~my_BufferedIntDoubleArray()
226/// {
227/// assert(0 <= d_length);
228/// assert(0 <= d_capacity);
229/// assert(d_length <= d_capacity);
230/// }
231///
232/// // MANIPULATORS
233/// void my_BufferedIntDoubleArray::appendDouble(double value)
234/// {
235/// if (d_length >= d_capacity) {
236/// increaseCapacity();
237/// }
238///
239/// double *item = static_cast<double *>(d_pool.allocate(sizeof *item));
240/// *item = value;
241///
242/// d_typeArray_p[d_length] = static_cast<char>(k_MY_DOUBLE);
243/// d_valueArray_p[d_length] = item;
244///
245/// ++d_length;
246/// }
247///
248/// void my_BufferedIntDoubleArray::appendInt(int value)
249/// {
250/// if (d_length >= d_capacity) {
251/// increaseCapacity();
252/// }
253///
254/// int *item = static_cast<int *>(d_pool.allocate(sizeof *item));
255/// *item = value;
256///
257/// d_typeArray_p[d_length] = static_cast<char>(k_MY_INT);
258/// d_valueArray_p[d_length] = item;
259///
260/// ++d_length;
261/// }
262/// @endcode
263///
264/// ### Example 2: Implementing an Allocator Using bdlma::BufferedSequentialPool {#bdlma_bufferedsequentialpool-example-2-implementing-an-allocator-using-bdlma-bufferedsequentialpool}
265///
266///
267/// `bslma::Allocator` is used throughout the interfaces of BDE components.
268/// Suppose we would like to create a fast allocator, `my_FastAllocator`, that
269/// allocates memory from a buffer in a similar fashion to
270/// `bdlma::BufferedSequentialPool`. `bdlma::BufferedSequentialPool` can be
271/// used directly to implement such an allocator.
272///
273/// Note that the documentation for this class is simplified for this usage
274/// example. Please see @ref bdlma_bufferedsequentialallocator for full
275/// documentation of a similar class.
276/// @code
277/// /// This class implements the `bslma::Allocator` protocol to provide a
278/// /// fast allocator of heterogeneous blocks of memory (of varying,
279/// /// user-specified sizes) from an external buffer whose address and size
280/// /// are supplied at construction.
281/// class my_FastAllocator : public bslma::Allocator {
282///
283/// // DATA
284/// bdlma::BufferedSequentialPool d_pool; // memory manager for allocated
285/// // memory blocks
286///
287/// // CREATORS
288///
289/// /// Create an allocator for allocating memory blocks from the
290/// /// specified external `buffer` of the specified `size` (in bytes).
291/// /// Optionally specify a `basicAllocator` used to supply memory
292/// /// should the capacity of `buffer` be exhausted. If
293/// /// `basicAllocator` is 0, the currently installed default allocator
294/// /// is used.
295/// my_FastAllocator(char *buffer,
296/// int size,
297/// bslma::Allocator *basicAllocator = 0);
298///
299/// /// Destroy this allocator. All memory allocated from this
300/// /// allocator is released.
301/// ~my_FastAllocator();
302///
303/// // MANIPULATORS
304///
305/// /// Return the address of a contiguous block of memory of the
306/// /// specified `size` (in bytes).
307/// virtual void *allocate(size_type size);
308///
309/// /// This method has no effect on the memory block at the specified
310/// /// `address` as all memory allocated by this allocator is managed.
311/// /// The behavior is undefined unless `address` was allocated by this
312/// /// allocator, and has not already been deallocated.
313/// virtual void deallocate(void *address);
314/// };
315///
316/// // CREATORS
317/// inline
318/// my_FastAllocator::my_FastAllocator(char *buffer,
319/// int size,
320/// bslma::Allocator *basicAllocator)
321/// : d_pool(buffer, size, basicAllocator)
322/// {
323/// }
324///
325/// inline
326/// my_FastAllocator::~my_FastAllocator()
327/// {
328/// d_pool.release();
329/// }
330///
331/// // MANIPULATORS
332/// inline
333/// void *my_FastAllocator::allocate(size_type size)
334/// {
335/// return d_pool.allocate(size);
336/// }
337///
338/// inline
339/// void my_FastAllocator::deallocate(void *)
340/// {
341/// }
342/// @endcode
343/// @}
344/** @} */
345/** @} */
346
347/** @addtogroup bdl
348 * @{
349 */
350/** @addtogroup bdlma
351 * @{
352 */
353/** @addtogroup bdlma_bufferedsequentialpool
354 * @{
355 */
356
357#include <bdlscm_version.h>
358
359#include <bdlma_buffermanager.h>
360#include <bdlma_sequentialpool.h>
361
362#include <bslma_allocator.h>
363
364#include <bsls_alignment.h>
365#include <bsls_assert.h>
366#include <bsls_blockgrowth.h>
367#include <bsls_platform.h>
368#include <bsls_performancehint.h>
369#include <bsls_types.h>
370
371#include <bsl_cstddef.h>
372
373
374namespace bdlma {
375
376 // ============================
377 // class BufferedSequentialPool
378 // ============================
379
380/// This class implements a fast memory pool that efficiently dispenses
381/// heterogeneous blocks of memory (of varying, user-specified sizes) from
382/// an external buffer whose address and size (in bytes) are supplied at
383/// construction. If an allocation request exceeds the remaining free
384/// memory space in the external buffer, memory will be supplied by an
385/// (optional) allocator supplied also at construction; if no allocator is
386/// supplied, the currently installed default allocator will be used. This
387/// class is *exception* *neutral*: If memory cannot be allocated, the
388/// behavior is defined by the (optional) allocator supplied at construction.
389///
390/// \note Note that in no case will the buffered sequential pool
391/// attempt to deallocate the external buffer.
392///
393/// See @ref bdlma_bufferedsequentialpool
395
396 // DATA
397 BufferManager d_bufferManager; // memory manager for current
398 // buffer
399
400 bsls::Types::size_type d_maxBufferSize; // max buffer size parameter to
401 // be passed to the sequential
402 // allocator upon construction
403
404 unsigned char d_growthStrategy; // the growth strategy to be
405 // passed to the sequential
406 // pool
407
408 bool d_sequentialPoolIsCreated;
409 // indicates whether the
410 // sequential pool has been
411 // created yet
412
413 union {
414 bslma::Allocator *d_allocator_p; // allocator we were
415 // constructed with if the
416 // sequential pool hasn't been
417 // created
418
419 SequentialPool *d_pool_p; // memory manager for
420 }; // allocations not from the
421 // buffer, if the sequential
422 // pool has been created
423
424 private:
425 // NOT IMPLEMENTED
428
429 private:
430 // PRIVATE MANIPULATORS
431
432 /// Allocate and construct the sequential pool, using a block size of
433 /// `bufferManager.bufferSize()`. Use the specified
434 /// `currentAllocationSize` to determine if the current allocation
435 /// attempt will fit in the first block, and thus what boolean value to
436 /// pass to the sequental pool's `allocateInitialBuffer` argument.
437 void createSequentialPool(bsls::Types::size_type currentAllocationSize);
438
439 // PRIVATE ACCESSORS
440
441 /// Return the alignment strategy to be used by the sequential pool.
442 bsls::Alignment::Strategy alignmentStrategy() const;
443
444 /// Return the growth strategy to be used by the sequential pool.
445 bsls::BlockGrowth::Strategy growthStrategy() const;
446
447 public:
448 // CREATORS
449
450 /// Create a buffered sequential pool for allocating memory blocks from
451 /// the specified external `buffer` having the specified `size` (in
452 /// bytes), or from an internal buffer (after the external `buffer` is
453 /// exhausted). Optionally specify a `growthStrategy` used to control
454 /// buffer growth. If a `growthStrategy` is not specified, geometric
455 /// growth is used. Optionally specify an `alignmentStrategy` used to
456 /// align allocated memory blocks. If an `alignmentStrategy` is not
457 /// specified, natural alignment is used. Optionally specify a
458 /// `basicAllocator` used to supply memory should the capacity of
459 /// `buffer` be exhausted. If `basicAllocator` is 0, the currently
460 /// installed default allocator is used.
461 ///
462 /// \pre The behavior is undefined unless `0 < size`, and `buffer` has at least `size` bytes.
463 ///
464 /// \note Note that, due to alignment effects, it is possible that not all `size`
465 /// bytes of memory in `buffer` can be used for allocation. Also note
466 /// that no limit is imposed on the size of the internal buffers when
467 /// geometric growth is used. Also note that when constant growth is
468 /// used, the size of the internal buffers will always be the same as
469 /// `size`.
472 bslma::Allocator *basicAllocator = 0);
475 bsls::BlockGrowth::Strategy growthStrategy,
476 bslma::Allocator *basicAllocator = 0);
479 bsls::Alignment::Strategy alignmentStrategy,
480 bslma::Allocator *basicAllocator = 0);
483 bsls::BlockGrowth::Strategy growthStrategy,
484 bsls::Alignment::Strategy alignmentStrategy,
485 bslma::Allocator *basicAllocator = 0);
486
487 /// Create a buffered sequential pool for allocating memory blocks from
488 /// the specified external `buffer` having the specified `size` (in
489 /// bytes), or from an internal buffer (after the external `buffer` is
490 /// exhausted) where the buffer growth is limited to the specified
491 /// `maxBufferSize` (in bytes). Optionally specify a `growthStrategy`
492 /// used to control buffer growth. If a `growthStrategy` is not
493 /// specified, geometric growth is used. Optionally specify an
494 /// `alignmentStrategy` used to align allocated memory blocks. If an
495 /// `alignmentStrategy` is not specified, natural alignment is used.
496 /// Optionally specify a `basicAllocator` used to supply memory should
497 /// the capacity of `buffer` be exhausted. If `basicAllocator` is 0,
498 /// the currently installed default allocator is used.
499 ///
500 /// \pre The behavior is undefined unless `0 < size`, `size <= maxBufferSize`, and `buffer` has at least `size` bytes.
501 ///
502 /// \note Note that, due to alignment effects, it
503 /// is possible that not all `size` bytes of memory in `buffer` can be
504 /// used for allocation. Also note that when constant growth is used,
505 /// the size of the internal buffers will always be the same as `size`.
508 bsls::Types::size_type maxBufferSize,
509 bslma::Allocator *basicAllocator = 0);
512 bsls::Types::size_type maxBufferSize,
513 bsls::BlockGrowth::Strategy growthStrategy,
514 bslma::Allocator *basicAllocator = 0);
517 bsls::Types::size_type maxBufferSize,
518 bsls::Alignment::Strategy alignmentStrategy,
519 bslma::Allocator *basicAllocator = 0);
522 bsls::Types::size_type maxBufferSize,
523 bsls::BlockGrowth::Strategy growthStrategy,
524 bsls::Alignment::Strategy alignmentStrategy,
525 bslma::Allocator *basicAllocator = 0);
526
527 /// Destroy this buffered sequential pool. All memory allocated from
528 /// this pool is released.
530
531 // MANIPULATORS
532
533 /// Return the address of a contiguous block of memory of the specified
534 /// `size` (in bytes) according to the alignment strategy specified at
535 /// construction. If `size` is 0, no memory is allocated and 0 is
536 /// returned. If the allocation request exceeds the remaining free
537 /// memory space in the external buffer supplied at construction, use
538 /// memory obtained from the allocator supplied at construction.
540
541 /// Destroy the specified `object`.
542 /// \note Note that this method has the same
543 /// effect as the `deleteObjectRaw` method (since no deallocation is
544 /// involved), and exists for consistency across memory pools.
545 template <class TYPE>
546 void deleteObject(const TYPE *object);
547
548 /// Destroy the specified `object`.
549 /// \note Note that memory associated with
550 /// `object` is not deallocated because there is no `deallocate` method
551 /// in `BufferedSequentialPool`.
552 template <class TYPE>
553 void deleteObjectRaw(const TYPE *object);
554
555 /// Release all memory allocated through this pool and return to the
556 /// underlying allocator *all* memory except the external buffer
557 /// supplied at construction. The pool is reset to its
558 /// default-constructed state, making the memory from the entire
559 /// external buffer supplied at construction available for subsequent
560 /// allocations, retaining the alignment and growth strategies, and the
561 /// initial and maximum buffer sizes in effect following construction.
562 /// The effect of subsequently - to this invokation of `release` - using
563 /// a pointer obtained from this object prior to this call to `release`
564 /// is undefined.
565 void release();
566
567 /// Release all memory allocated through this pool and return to the
568 /// underlying allocator *only* memory that was allocated outside of the
569 /// typical internal buffer growth of this pool (i.e., large blocks).
570 /// All retained memory will be used to satisfy subsequent allocations.
571 /// The effect of subsequently - to this invokation of `rewind` - using
572 /// a pointer obtained from this object prior to this call to `rewind`
573 /// is undefined.
574 void rewind();
575
576 // ACCESSORS
577
578 /// Return the allocator used by this object to allocate memory.
579 ///
580 /// \note Note that this allocator can not be used to deallocate memory allocated
581 /// through this pool.
583};
584
585} // close package namespace
586
587
588// Note that the `new` and `delete` operators are declared outside the
589// `BloombergLP` namespace so that they do not hide the standard placement
590// `new` and `delete` operators (i.e.,
591// `void *operator new(bsl::size_t, void *)` and
592// `void operator delete(void *)`).
593//
594// Also note that only the scalar versions of operators `new` and `delete` are
595// provided, because overloading `new` (and `delete`) with their array versions
596// would cause dangerous ambiguity. Consider what would have happened had we
597// overloaded the array version of `operator new`:
598//..
599// void *operator new[](bsl::size_t size,
600// BloombergLP::bdlma::BufferedSequentialPool& pool);
601//..
602// The user of the pool class would have expected to be able to use operator
603// `new` as follows:
604//..
605// new (*pool) my_Type[...];
606//..
607// The problem is that this expression returns an array that cannot be safely
608// deallocated. On the one hand, there is no syntax in C++ to invoke an
609// overloaded `operator delete`; on the other hand, the pointer returned by
610// `operator new` cannot be passed to the `deallocate` method directly because
611// the pointer is different from the one returned by the `allocate` method.
612// The compiler offsets the value of this pointer by a header, which is used to
613// maintain the number of objects in the array (so that the `operator delete`
614// can destroy the right number of objects).
615
616// FREE OPERATORS
617
618/// Return a block of memory of the specified `size` (in bytes) allocated from the specified `pool`.
619///
620/// \note Note that an object may allocate additional
621/// memory internally, requiring the allocator to be passed in as a
622/// constructor argument:
623/// @code
624/// my_Type *newMyType(bdlma::BufferedSequentialPool *pool,
625/// bslma::Allocator *basicAllocator)
626/// {
627/// return new (*pool) my_Type(..., basicAllocator);
628/// }
629/// @endcode
630/// Also note that the analogous version of `operator delete` should not be
631/// called directly. Instead, this component provides a static template
632/// member function, `deleteObject`, parameterized by `TYPE` that performs
633/// the following:
634/// @code
635/// void deleteMyType(bdlma::BufferedSequentialPool *pool, my_Type *t)
636/// {
637/// t->~my_Type();
638/// }
639/// @endcode
640void *operator new(bsl::size_t size,
641 BloombergLP::bdlma::BufferedSequentialPool& pool);
642
643/// Use the specified `pool` to deallocate the memory at the specified `address`.
644///
645/// \pre The behavior is undefined unless `address` was allocated
646/// using `pool` and has not already been deallocated. This operator is
647/// supplied solely to allow the compiler to arrange for it to be called in
648/// case of an exception.
649void operator delete(void *address,
650 BloombergLP::bdlma::BufferedSequentialPool& pool);
651
652// ============================================================================
653// INLINE DEFINITIONS
654// ============================================================================
655
656
657namespace bdlma {
658
659 // ----------------------------
660 // class BufferedSequentialPool
661 // ----------------------------
662
663// PRIVATE ACCESSORS
664inline
665bsls::Alignment::Strategy BufferedSequentialPool::alignmentStrategy() const
666{
667 return d_bufferManager.alignmentStrategy();
668}
669
670inline
671bsls::BlockGrowth::Strategy BufferedSequentialPool::growthStrategy() const
672{
673 return static_cast<bsls::BlockGrowth::Strategy>(d_growthStrategy);
674}
675
676// CREATORS
677inline
679{
680 // 'd_bufferManager' doesn't need to be released, it will destroy itself
681 // just fine.
682
683 if (d_sequentialPoolIsCreated) {
685 }
686}
687
688// MANIPULATORS
689inline
691{
694 return 0; // RETURN
695 }
696
697 void *result = d_bufferManager.allocate(size);
699 return result; // RETURN
700 }
701
702 if (false == d_sequentialPoolIsCreated) {
703 this->createSequentialPool(size);
704 }
705
706 return d_pool_p->allocate(size);
707}
708
709template <class TYPE>
710inline
712{
713 this->deleteObjectRaw(object);
714}
715
716template <class TYPE>
717inline
719{
720 if (0 != object) {
721#ifndef BSLS_PLATFORM_CMP_SUN
722 object->~TYPE();
723#else
724 const_cast<TYPE *>(object)->~TYPE();
725#endif
726 }
727}
728
729inline
731{
732 d_bufferManager.release(); // Reset the internal cursor in the current
733 // block.
734
735 if (d_sequentialPoolIsCreated) {
736 // Note that 'd_pool_p' and 'd_allocator_p' fit in the same footprint
737 // in an anonymous union.
738
739 bslma::Allocator *alloc_p = d_pool_p->allocator();
740 alloc_p->deleteObjectRaw(d_pool_p);
741 d_allocator_p = alloc_p;
742
743 d_sequentialPoolIsCreated = false;
744 }
745}
746
747inline
749
750{
751 d_bufferManager.release(); // Reset the internal cursor in the current
752 // block.
753
754 if (d_sequentialPoolIsCreated) {
755 d_pool_p->rewind();
756 }
757}
758
759// ACCESSORS
760inline
762{
763 return d_sequentialPoolIsCreated ? d_pool_p->allocator()
765}
766
767} // close package namespace
768
769
770// FREE OPERATORS
771inline
772void *operator new(bsl::size_t size,
773 BloombergLP::bdlma::BufferedSequentialPool& pool)
774{
775 return pool.allocate(size);
776}
777
778inline
779void operator delete(void *, BloombergLP::bdlma::BufferedSequentialPool&)
780{
781 // NOTE: there is no deallocation from this allocation mechanism.
782}
783
784#endif
785
786// ----------------------------------------------------------------------------
787// Copyright 2016 Bloomberg Finance L.P.
788//
789// Licensed under the Apache License, Version 2.0 (the "License");
790// you may not use this file except in compliance with the License.
791// You may obtain a copy of the License at
792//
793// http://www.apache.org/licenses/LICENSE-2.0
794//
795// Unless required by applicable law or agreed to in writing, software
796// distributed under the License is distributed on an "AS IS" BASIS,
797// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
798// See the License for the specific language governing permissions and
799// limitations under the License.
800// ----------------------------- END-OF-FILE ----------------------------------
801
802/** @} */
803/** @} */
804/** @} */
Definition bdlma_buffermanager.h:312
void release()
Definition bdlma_buffermanager.h:611
bsls::Alignment::Strategy alignmentStrategy() const
Definition bdlma_buffermanager.h:626
void * allocate(bsls::Types::size_type size)
Definition bdlma_buffermanager.h:537
Definition bdlma_bufferedsequentialpool.h:394
~BufferedSequentialPool()
Definition bdlma_bufferedsequentialpool.h:678
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:718
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:711
bslma::Allocator * d_allocator_p
Definition bdlma_bufferedsequentialpool.h:414
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:419
bslma::Allocator * allocator() const
Definition bdlma_bufferedsequentialpool.h:761
void release()
Definition bdlma_bufferedsequentialpool.h:730
void rewind()
Definition bdlma_bufferedsequentialpool.h:748
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:690
Definition bdlma_sequentialpool.h:383
bslma::Allocator * allocator() const
Definition bdlma_sequentialpool.h:835
void * allocate(bsls::Types::size_type size)
Definition bdlma_sequentialpool.h:777
Definition bslma_allocator.h:545
void deleteObjectRaw(const TYPE *object)
Definition bslma_allocator.h:804
virtual void * allocate(size_type size)=0
#define BSLS_IDENT(str)
BSLS_IDENT() - insert string into .comment binary segment (if supported)
Definition bsls_ident.h:238
#define BSLS_PERFORMANCEHINT_PREDICT_LIKELY(expr)
Definition bsls_performancehint.h:451
#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:278
Strategy
Types of alignment strategy.
Definition bsls_alignment.h:241
Strategy
Definition bsls_blockgrowth.h:172
std::size_t size_type
Definition bsls_types.h:126