BDE 4.39.x Production Release
Loading...
Searching...
No Matches
bslma_allocator.h
Go to the documentation of this file.
1/// @file bslma_allocator.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bslma_allocator.h -*-C++-*-
8#ifndef INCLUDED_BSLMA_ALLOCATOR
9#define INCLUDED_BSLMA_ALLOCATOR
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bslma_allocator bslma_allocator
15/// @brief Provide a pure abstract interface for memory-allocation mechanisms.
16/// @addtogroup bsl
17/// @{
18/// @addtogroup bslma
19/// @{
20/// @addtogroup bslma_allocator
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bslma_allocator-purpose"> Purpose</a>
25/// * <a href="#bslma_allocator-classes"> Classes </a>
26/// * <a href="#bslma_allocator-description"> Description </a>
27/// * <a href="#bslma_allocator-thread-safety"> Thread Safety </a>
28/// * <a href="#bslma_allocator-allocators-versus-pools"> Allocators Versus Pools </a>
29/// * <a href="#bslma_allocator-overloaded-global-operators-new-and-delete"> Overloaded Global Operators new and delete </a>
30/// * <a href="#bslma_allocator-usage"> Usage </a>
31/// * <a href="#bslma_allocator-example-1-derived-concrete-allocator"> Example 1: Derived Concrete Allocator </a>
32/// * <a href="#bslma_allocator-example-2-container-objects"> Example 2: Container Objects </a>
33///
34/// # Purpose {#bslma_allocator-purpose}
35/// Provide a pure abstract interface for memory-allocation mechanisms.
36///
37/// # Classes {#bslma_allocator-classes}
38///
39/// - bslma::Allocator: protocol class for memory allocation and deallocation
40///
41/// @see bslma_newdeleteallocator, bslma_testallocator
42///
43/// # Description {#bslma_allocator-description}
44/// This component provides the base-level protocol (pure abstract
45/// interface) class, @ref bslma_allocator , that serves as a ubiquitous vocabulary
46/// type for various memory allocation mechanisms. The functional capabilities
47/// documented by this protocol are similar to those afforded by global
48/// operators `new` and `delete`: sufficiently (but not necessarily maximally)
49/// aligned memory is guaranteed for any object of a given size. Clients of
50/// this abstract base class will typically accept a supplied allocator (often
51/// at construction) and use its `allocate` and `deallocate` methods instead of
52/// `new` and `delete` directly.
53///
54/// The use of (abstract) allocators provides at least three distinct advantages
55/// over direct (hard-coded) calls to global `new` and `delete` (see
56/// @ref bslma_newdeleteallocator ):
57///
58/// 1. The particular choice of allocator can be selected to improve performance
59/// on a per-object basis. Without allocators, the best we can do in C++ is
60/// to overload the class-specific new and delete. Class-specific allocators
61/// tend to hoard memory even when most objects of the class have been
62/// deallocated, and often mask memory leaks that would otherwise have been
63/// detected. See Lakos-96, Section 10.3.4.2, pp 705-711.
64/// 2. By providing extra capabilities (beyond `new` and `delete`) in the
65/// derived class (see @ref bslma_managedallocator ), we can bypass the
66/// individual destructors in a dynamically allocated type and remove all
67/// memory for one or more associated object almost instantly.
68/// 3. The `bslma::Allocator` protocol, like any other protocol, isolates
69/// clients from direct coupling with platform level facilities that are not
70/// fully under their control. By installing a test allocator (see
71/// @ref bslma_testallocator ), we are able to orchestrate the white-box testing
72/// of internal calls to global operators `new` and `delete` in a
73/// platform-neutral manner.
74///
75/// ## Thread Safety {#bslma_allocator-thread-safety}
76///
77///
78/// Unless otherwise documented, a single allocator object is not safe for
79/// concurrent access by multiple threads. Classes derived from
80/// `bslma::Allocator` that are specifically designed for concurrent access must
81/// be documented as such. Unless specifically documented otherwise, separate
82/// objects of classes derived from `bslma::Allocator` may safely be used in
83/// separate threads.
84///
85/// ## Allocators Versus Pools {#bslma_allocator-allocators-versus-pools}
86///
87///
88/// An allocator and a pool are quite different. For starters,
89/// `bslma::Allocator` is an abstract class used to obtain "raw" memory of
90/// arbitrary size. A pool is a concrete data structure used to organize and
91/// supply memory according to specific needs (e.g., a consistent size).
92/// Concrete allocators may use pools in their implementations, and pools will
93/// always take a base `bslma::Allocator` protocol in their interface. You can
94/// think of an allocator as a stream of memory that flows into a pool of
95/// memory. Memory is allocated from the pool until it is dry; only then does
96/// new memory flow into the pool from the allocator.
97///
98/// ## Overloaded Global Operators new and delete {#bslma_allocator-overloaded-global-operators-new-and-delete}
99///
100///
101/// This component overloads the global operator `new` to allow convenient
102/// syntax for the construction of objects using the `bslma::Allocator`
103/// protocol. The overloaded `new` operator defined in this component has a
104/// second parameter, `bslma::Allocator&`, that identifies the concrete
105/// (derived) allocator that will be used to supply memory.
106///
107/// Consider the following use of standard placement syntax (supplied by
108/// `#include <new>`) along with a `bslma::Allocator`, used to allocate an
109/// arbitrary `TYPE`.
110/// @code
111/// void someFunction(bslma::Allocator *basicAllocator)
112/// {
113/// TYPE *obj = new (basicAllocator->allocate(sizeof(TYPE))) TYPE(...);
114///
115/// // ...
116/// @endcode
117/// This style of usage is inconvenient and error prone; it is also *not*
118/// exception safe: If the constructor of `TYPE` throws an exception, the
119/// `basicAllocator->deallocate` method is never called.
120///
121/// Providing an overloaded global operator `new`, taking a reference to a
122/// modifiable `bslma::Allocator` as an explicit argument allows for cleaner
123/// usage and guarantees that the `basicAllocator->deallocate` method is called
124/// in case of an exception:
125/// @code
126/// void someFunction(bslma::Allocator *basicAllocator)
127/// {
128/// TYPE *obj = new (*basicAllocator) TYPE(...);
129///
130/// // ...
131/// @endcode
132/// Finally, the analogous version of operator `delete` should not be called
133/// directly: The overloaded operator `delete` supplied in this component is
134/// solely for the compiler to invoke in the event an exception is thrown during
135/// a failed construction. Instead, the `bslma::Allocator` protocol provides
136/// `deleteObject` (a template member function parameterized by the type of the
137/// object being deleted), which is implemented *conceptually* as follows:
138/// @code
139/// template <class TYPE>
140/// void bslma::Allocator::deleteObject(TYPE *address)
141/// {
142/// address->~TYPE();
143/// this->deallocate(address);
144/// }
145/// @endcode
146/// Note that there is also a `deleteObjectRaw` which is more efficient when it
147/// is known that the `address` does *not* refer to a secondary base class of
148/// the object being deleted.
149///
150/// ## Usage {#bslma_allocator-usage}
151///
152///
153/// The `bslma::Allocator` protocol provided in this component defines a
154/// bilateral contract between suppliers and consumers of raw memory. The
155/// following subsections illustrate (1) use, and (2) implementation of the
156/// abstract `bslma::Allocator` base class:
157///
158/// ### Example 1: Derived Concrete Allocator {#bslma_allocator-example-1-derived-concrete-allocator}
159///
160///
161/// In order for the `bslma::Allocator` interface to be useful, we must supply a
162/// concrete allocator that implements it. In this example we demonstrate how
163/// to adapt `operator new` and `operator delete` to this protocol base class.
164///
165/// First, in a component `.h` file, we define a class, derived from
166/// `bslma::Allocator`, that provides concrete implementations of the `virtual`
167/// `allocate` and `deallocate` methods:
168/// @code
169/// // my_newdeleteallocator.h
170/// // ...
171///
172/// #include <bslma_allocator.h>
173/// #include <bsls_keyword.h>
174/// #include <new>
175///
176/// /// This class is a sample concrete implementation of the
177/// /// `bslma::Allocator` protocol that provides direct access to the
178/// /// system-supplied (native) global operators `new` and `delete`.
179/// class my_NewDeleteAllocator : public bslma::Allocator {
180///
181/// private:
182/// // NOT IMPLEMENTED
183/// my_NewDeleteAllocator(const my_NewDeleteAllocator&);
184/// my_NewDeleteAllocator& operator=(const my_NewDeleteAllocator&);
185///
186/// public:
187/// // CLASS METHODS
188///
189/// /// Return the address of a singleton object of
190/// /// `my_NewDeleteAllocator`. Since `my_NewDeleteAllocator` has no
191/// /// state, there is never a need for more than one.
192/// static my_NewDeleteAllocator *singleton();
193///
194/// // CREATORS
195///
196/// /// Create an allocator that wraps the global (native) operators
197/// /// `new` and `delete` to supply memory. Note that all objects of
198/// /// this class share the same underlying resource.
199/// my_NewDeleteAllocator() { }
200///
201/// /// Destroy this allocator object. Note that destroying this
202/// /// allocator has no effect on any outstanding allocated memory.
203/// ~my_NewDeleteAllocator() BSLS_KEYWORD_OVERRIDE;
204///
205/// // MANIPULATORS
206///
207/// /// Return a newly allocated block of memory of (at least) the
208/// /// specified positive `size` (in bytes). If `size` is 0, a null
209/// /// pointer is returned with no other effect. If this allocator
210/// /// cannot return the requested number of bytes, then it will throw
211/// /// a `std::bad_alloc` exception in an exception-enabled build, or
212/// /// else will abort the program in a non-exception build. The
213/// /// behavior is undefined unless `0 <= size`. Note that the
214/// /// alignment of the address returned is the maximum alignment for
215/// /// any type defined on this platform. Also note that global
216/// /// `operator new` is *not* called when `size` is 0 (in order to
217/// /// avoid having to acquire a lock, and potential contention in
218/// /// multi-threaded programs).
219/// void *allocate(size_type size) BSLS_KEYWORD_OVERRIDE;
220///
221/// /// Return the memory block at the specified `address` back to this
222/// /// allocator. If `address` is 0, this function has no effect. The
223/// /// behavior is undefined unless `address` was allocated using this
224/// /// allocator object and has not already been deallocated. Note
225/// /// that global `operator delete` is *not* called when `address` is
226/// /// 0 (in order to avoid having to acquire a lock, and potential
227/// /// contention in multi-treaded programs).
228/// void deallocate(void *address) BSLS_KEYWORD_OVERRIDE;
229/// };
230/// @endcode
231/// Next, in the component `.cpp` file, we define the `singleton()` method,
232/// which provides the typical way of obtaining an instance of this allocator:
233/// @code
234/// // my_newdeleteallocator.cpp
235/// #include <my_newdeleteallocator.h>
236///
237/// // CLASS METHODS
238/// my_NewDeleteAllocator *my_NewDeleteAllocator::singleton()
239/// {
240/// static my_NewDeleteAllocator obj;
241/// return &obj;
242/// }
243/// @endcode
244/// Next, we implement the `bslma::Allocator` protocol by defining (also in the
245/// component `.cpp` file) the virtual methods:
246/// @code
247/// // CREATORS
248/// my_NewDeleteAllocator::~my_NewDeleteAllocator()
249/// {
250/// }
251///
252/// // MANIPULATORS
253/// void *my_NewDeleteAllocator::allocate(size_type size)
254/// {
255/// return 0 == size ? 0 : ::operator new(size);
256/// }
257///
258/// void my_NewDeleteAllocator::deallocate(void *address)
259/// {
260/// // While the C++ standard guarantees that calling delete(0) is safe
261/// // (3.7.3.2 paragraph 3), some libc implementations take out a lock to
262/// // deal with the free(0) case, so this check can improve efficiency of
263/// // threaded programs.
264///
265/// if (address) {
266/// ::operator delete(address);
267/// }
268/// }
269/// @endcode
270/// Now we can use `my_NewDeleteAllocator` to allocate and deallocate storage
271/// for (in this case, `int`) objects:
272/// @code
273/// int main()
274/// {
275/// typedef int T; // Can be any type
276///
277/// my_NewDeleteAllocator myA;
278/// T *p = static_cast<T *>(myA.allocate(sizeof(T)));
279/// new (p) T(5); // Construct object at `p`.
280/// assert(5 == *p);
281/// p->~T(); // not needed for `int`, but important for class types
282/// myA.deallocate(p);
283/// @endcode
284/// Finally, we repeat the previous example using the `singleton` object instead
285/// of constructing a new `my_NewDeleteAllocator` and using the `operator new`
286/// and `deleteObject` interface instead of raw `allocate`-construct and
287/// destroy-`deallocate`. Note that these interfaces can be mixed and matched
288/// (e.g., `singleton` can be used with `allocate`):
289/// @code
290/// p = new (*my_NewDeleteAllocator::singleton()) T(6);
291/// assert(6 == *p);
292/// my_NewDeleteAllocator::singleton()->deleteObject(p);
293/// }
294/// @endcode
295///
296/// ### Example 2: Container Objects {#bslma_allocator-example-2-container-objects}
297///
298///
299/// Allocators are often supplied to objects requiring dynamically-allocated
300/// memory at construction. For example, consider the following
301/// `my_DoubleStack` class, which uses a `bslma::Allocator` to allocate memory.
302///
303/// First, we define the class interface, which is a minimal subset of a typical
304/// container interface:
305/// @code
306/// // my_doublestack.h
307/// // ...
308///
309/// #include <bslma_allocator.h>
310/// #include <my_NewDeleteAllocator.h>
311///
312/// /// dynamically growing stack of `double` values
313/// class my_DoubleStack {
314/// enum { k_INITIAL_SIZE = 1, k_GROWTH_FACTOR = 2 };
315///
316/// int d_capacity; // physical capacity of this stack (in
317/// // elements)
318/// int d_size; // number of available stack elements
319/// // currently in use
320/// double *d_stack_p; // dynamically allocated array of
321/// // `d_capacity` elements
322/// bslma::Allocator *d_allocator_p; // holds (but doesn't own) allocator
323///
324/// private:
325/// /// Increase the capacity by `k_GROWTH_FACTOR`.
326/// void increaseSize();
327///
328/// public:
329/// // CREATORS
330/// explicit my_DoubleStack(bslma::Allocator *basicAllocator = 0);
331/// my_DoubleStack(const my_DoubleStack& other,
332/// bslma::Allocator *basicAllocator = 0);
333/// ~my_DoubleStack();
334///
335/// // MANIPULATORS
336/// my_DoubleStack& operator=(const my_DoubleStack& rhs);
337/// void pop() { --d_size; }
338/// void push(double value);
339///
340/// // ACCESSORS
341/// double operator[](int i) const { return d_stack_p[i]; }
342/// bslma::Allocator *allocator() const { return d_allocator_p; }
343/// int capacity() const { return d_capacity; }
344/// bool isEmpty() const { return 0 == d_size; }
345/// int size() const { return d_size; }
346/// double top() const { return d_stack_p[d_size - 1]; }
347/// };
348/// @endcode
349/// Next, we define the constructor, which takes an optional `basicAllocator`
350/// supplied only at construction. (We avoid use of the name `allocator` so as
351/// not to conflict with the STL use of the word, which differs slightly.) If
352/// non-zero, the stack holds a pointer to this allocator, but does not own it.
353/// If no allocator is supplied, the implementation itself must either
354/// conditionally invoke global `new` and `delete` explicitly whenever dynamic
355/// memory must be managed (BAD IDEA) or (GOOD IDEA) install a default allocator
356/// that adapts use of these global operators to the @ref bslma_allocator interface
357/// (see @ref bslma_default ). The constructor uses the selected allocator to
358/// allocate memory via the `allocate` method.
359/// @code
360/// // my_doublestack.cpp
361/// #include <my_doublestack.h>
362/// #include <bslma_allocator.h>
363/// #include <bslma_default.h> // for selecting a default allocator
364///
365/// // CREATORS
366/// my_DoubleStack::my_DoubleStack(bslma::Allocator *basicAllocator)
367/// : d_capacity(k_INITIAL_SIZE)
368/// , d_size(0)
369/// , d_allocator_p(basicAllocator ?
370/// basicAllocator : my_NewDeleteAllocator::singleton())
371/// // The above initialization expression is roughly equivalent to
372/// // `bslma::Default::allocator(basicAllocator)`
373/// {
374/// assert(d_allocator_p);
375/// d_stack_p = (double *)
376/// d_allocator_p->allocate(d_capacity * sizeof *d_stack_p);
377/// }
378/// @endcode
379/// Next, we define a destructor that frees the memory held by the container
380/// using the allocator's `deallocate` method:
381/// @code
382/// my_DoubleStack::~my_DoubleStack()
383/// {
384/// // CLASS INVARIANTS
385/// assert(d_allocator_p);
386/// assert(d_stack_p);
387/// assert(0 <= d_size);
388/// assert(0 <= d_capacity);
389/// assert(d_size <= d_capacity);
390///
391/// d_allocator_p->deallocate(d_stack_p);
392/// }
393/// @endcode
394/// Next, we define a `reallocation` function that expands a dynamic array of
395/// `double`s. Even in this simplified implementation, all use of the allocator
396/// protocol is relegated to the `.cpp` file:
397/// @code
398/// /// Reallocate memory in the specified `array` to the specified `newSize`
399/// /// using the specified `basicAllocator`. The specified `length` number of
400/// /// leading elements are preserved. Since the class invariant requires
401/// /// that the physical capacity of the container may grow but never shrink;
402/// /// the behavior is undefined unless `length <= newSize`.
403/// static inline
404/// void reallocate(double **array,
405/// int newSize,
406/// int length,
407/// bslma::Allocator *basicAllocator)
408/// {
409/// assert(array);
410/// assert(1 <= newSize);
411/// assert(0 <= length);
412/// assert(basicAllocator);
413/// assert(length <= newSize); // enforce class invariant
414///
415/// double *tmp = *array; // support exception neutrality
416/// *array = (double *) basicAllocator->allocate(newSize * sizeof **array);
417///
418/// // COMMIT POINT
419///
420/// memcpy(*array, tmp, length * sizeof **array);
421/// basicAllocator->deallocate(tmp);
422/// }
423/// @endcode
424/// Next, we define the private `increaseSize` method to allocate more space for
425/// container elements as needed:
426/// @code
427/// void my_DoubleStack::increaseSize()
428/// {
429/// int proposedNewSize = d_capacity * k_GROWTH_FACTOR;
430/// assert(proposedNewSize > d_size);
431///
432/// // Reallocate might throw.
433/// reallocate(&d_stack_p, proposedNewSize, d_size, d_allocator_p);
434///
435/// // Commit change only after `reallocate` succeeds.
436/// d_capacity = proposedNewSize;
437/// }
438/// @endcode
439/// Now we have what we need to implement the `push` method:
440/// @code
441/// void my_DoubleStack::push(double value)
442/// {
443/// if (d_size >= d_capacity) {
444/// increaseSize();
445/// }
446/// d_stack_p[d_size++] = value;
447/// }
448/// @endcode
449/// Now, to test our stack class, we first verify that its constructor captures
450/// the allocator correctly; if supplied an allocator pointer, it holds on to
451/// that pointer, otherwise it uses `my_NewDeleteAllocator::singleton()`:
452/// @code
453/// int main()
454/// {
455/// my_NewDeleteAllocator myA;
456///
457/// my_DoubleStack ds1(&myA); // Supply an allocator.
458/// assert(ds1.allocator() == &myA);
459///
460/// my_DoubleStack ds2; // Do not supply an allocator.
461/// assert(ds2.allocator() == my_NewDeleteAllocator::singleton());
462/// @endcode
463/// Finally, we exercise and verify the behavior of the manipulators and
464/// accessors:
465/// @code
466/// assert(ds2.isEmpty());
467/// assert(1 == ds2.capacity());
468/// ds2.push(1.25);
469/// ds2.push(1.5);
470/// ds2.push(1.75);
471///
472/// assert(! ds2.isEmpty());
473/// assert(4 == ds2.capacity());
474/// assert(3 == ds2.size());
475/// assert(1.75 == ds2.top());
476/// assert(1.25 == ds2[0]);
477/// assert(1.5 == ds2[1]);
478/// assert(1.75 == ds2[2]);
479///
480/// ds2.pop();
481/// assert(4 == ds2.capacity());
482/// assert(2 == ds2.size());
483/// assert(1.5 == ds2.top());
484/// }
485/// @endcode
486/// @}
487/** @} */
488/** @} */
489
490/** @addtogroup bsl
491 * @{
492 */
493/** @addtogroup bslma
494 * @{
495 */
496/** @addtogroup bslma_allocator
497 * @{
498 */
499
500#include <bslma_allocator.fwd.h>
501
502#include <bslscm_version.h>
503
504#include <bslma_deleterhelper.h>
505#include <bslma_memoryresource.h>
506
507#include <bsla_deprecated.h>
508
509#include <bslmf_assert.h>
510#include <bslmf_enableif.h>
513#include <bslmf_issame.h>
516
517#include <bsls_keyword.h>
518#include <bsls_nullptr.h>
519#include <bsls_platform.h>
520
521#include <cstddef> // for `std::size_t`, `std::ptrdiff_t`
522
523#ifndef BDE_DONT_ALLOW_TRANSITIVE_INCLUDES
524#include <bsls_cpp11.h>
525#endif
526
527
528
529namespace bslma {
530
531 // ===============
532 // class Allocator
533 // ===============
534
535/// This protocol class provides a pure abstract interface and contract for
536/// clients and suppliers of raw memory. If the requested memory cannot be
537/// returned, the contract requires that an `std::bad_alloc` exception be thrown.
538///
539/// \note Note that memory is guaranteed to be sufficiently aligned for
540/// any object of the requested size on the current platform, which may be
541/// less than the maximal alignment guarantee afforded by global
542/// `operator new`.
543///
544/// See @ref bslma_allocator
546
547 protected:
548 // PROTECTED MANIPULATORS
549
550 /// Return a newly allocated block of memory of (at least) the specified
551 /// positive `bytes` and having at least the specified `alignment`. Unless
552 /// overriden in a derived class, the return value is
553 /// `this->allocate(bytes)`. If this allocator cannot return the requested
554 /// number of bytes or cannot satisfy the alignment request, then it will
555 /// throw a `std::bad_alloc` exception in an exception-enabled build, or
556 /// else will abort the program in a non-exception build. Unless overriden
557 /// in a derived class, this function will forward the allocation request
558 /// to the `allocate` virtual function, padding `bytes` and adjusting the return value as necessary to ensure sufficient alignment.
559 ///
560 /// \note Note that if
561 /// `bytes` is `0`, the same non-null value will be returned every time.
562 void* do_allocate(std::size_t bytes,
563 std::size_t alignment) BSLS_KEYWORD_OVERRIDE;
564
565 /// Return the memory block at the specified `p` address, having the
566 /// specified `bytes` and specified `alignment`, back to this allocator.
567 /// Unless overriden in a derived class, this function will forward the
568 /// deallocation request to the `deallocate` virtual function, padding
569 /// `bytes` and adjusting `p` as necessary to account for `alignment`
570 /// values other than the natural alignment for an object of size `bytes`.
571 ///
572 /// \pre The behavior is undefined unless `address` is a block allocated from
573 /// this allocator object using the same `bytes` and `alignment` and not
574 /// already deallocated.
575 void do_deallocate(void *p,
576 std::size_t bytes,
577 std::size_t alignment) BSLS_KEYWORD_OVERRIDE;
578
579 // PROTECTED ACCESSORS
580
581 /// Return `true` if this allocator is equal to the specified `other`
582 /// allocator, meaning (at least) that a memory block allocated by one can
583 /// be deallocated by the other; otherwise return `false`. Unless
584 /// overriden, this method returns `this == &other`.
585 bool do_is_equal(const memory_resource& other) const
587
588 public:
589 // PUBLIC TYPES
590
591 /// Alias for an unsigned integral type capable of representing the number
592 /// of bytes in this platform's virtual address space.
593 typedef std::size_t size_type;
594
595#ifndef BDE_OMIT_INTERNAL_DEPRECATED
596 // CLASS METHODS
597
598 /// Throw `std::bad_alloc` if exceptions are enabled or abort the
599 /// program otherwise. Derived classes and helper functions will
600 /// typically call this function when they are unable to satisfy an
601 /// allocation request. This function never returns.
602 ///
603 /// @deprecated Use @ref bsls::BslExceptionUtil::throwBadAlloc instead.
604 static void throwBadAlloc();
605#endif // BDE_OMIT_INTERNAL_DEPRECATED
606
607 // CREATORS
608
609 /// Destroy this allocator.
610 /// \note Note that the behavior of destroying an
611 /// allocator while memory is allocated from it is not specified; unless
612 /// you *know* that it is valid to do so, don't!
614
615 // MANIPULATORS
616
617 /// Return a newly allocated block of memory of (at least) the specified
618 /// positive `size` (in bytes). If `size` is 0, a null pointer is
619 /// returned with no other effect. If this allocator cannot return the
620 /// requested number of bytes, then it will throw a `std::bad_alloc`
621 /// exception in an exception-enabled build, or else will abort the program in a non-exception build.
622 ///
623 /// \pre The behavior is undefined unless `0 <= size`.
624 ///
625 /// \note Note that the alignment of the address returned
626 /// conforms to the platform requirement for any object of the specified `size`.
627 ///
628 /// \note Note that this virtual function hides a two-parameter
629 /// non-virtual `allocate` method inherited from `bsl::memory_resource`;
630 /// to access the inherited function, upcast the object to
631 /// `bsl::memory_resource&` before calling the base-class function.
632 virtual void *allocate(size_type size) = 0;
633
634 /// Return the memory block at the specified `address` back to this
635 /// allocator. If `address` is 0, this function has no effect.
636 ///
637 /// \pre The behavior is undefined unless `address` was allocated using this
638 /// allocator object and has not already been deallocated.
639 ///
640 /// \note Note that this virtual function hides a three-parameter, non-virtual `deallocate`
641 /// method inherited from `bsl::memory_resource`; to access the
642 /// inherited function, upcast the object to `bsl::memory_resource&`
643 /// before calling the base-class function.
644 virtual void deallocate(void *address) = 0;
645
646 /// Destroy the specified `object` based on its dynamic type and then
647 /// use this allocator to deallocate its memory footprint. Do nothing if `object` is a null pointer.
648 ///
649 /// \pre The behavior is undefined unless
650 /// `object`, when cast appropriately to `void *`, was allocated using
651 /// this allocator and has not already been deallocated.
652 ///
653 /// \note Note that `dynamic_cast<void *>(object)` is applied if `TYPE` is polymorphic,
654 /// and `static_cast<void *>(object)` is applied otherwise.
655 template <class TYPE>
656 void deleteObject(const TYPE *object);
657
658 /// Destroy the specified `object` and then use this allocator to
659 /// deallocate its memory footprint. Do nothing if `object` is a null pointer.
660 ///
661 /// \pre The behavior is undefined unless `object` was allocated
662 /// using this allocator, is **not** a secondary base class pointer --
663 /// i.e., the address is (numerically) the same as when it was
664 /// originally dispensed by this allocator, and has not already been
665 /// deallocated.
666 template <class TYPE>
667 void deleteObjectRaw(const TYPE *object);
668
669 /// This function has no effect.
670 /// \note Note that it exists to support calling
671 /// `deleteObject` will a null pointer literal, that would otherwise not
672 /// deduce to a pointer type for the method above. As calls to
673 /// `deleteObject` with (typed) null pointer values have well-defined
674 /// behavior, it should also support calls with a null pointer literal.
675 void deleteObject(bsl::nullptr_t);
676
677 /// This function has no effect.
678 /// \note Note that it exists to support calling
679 /// `deleteObjectRaw` will a null pointer literal, that would otherwise
680 /// not deduce to a pointer type for the method above. As calls to
681 /// `deleteObjectRaw` with (typed) null pointer values have well-defined
682 /// behavior, it should also support calls with a null pointer literal.
683 void deleteObjectRaw(bsl::nullptr_t);
684};
685
686} // close package namespace
687
688
689// FREE OPERATORS
690
691// Note that the operators `new` and `delete` are declared outside the
692// `BloombergLP` namespace so that they do not hide the standard placement
693// `new` and `delete` operators (i.e.,
694// `void *operator new(std::size_t, void *)` and
695// `void operator delete(void *)`).
696//
697// Note also that only the scalar versions of operators `new` and `delete` are
698// provided, because overloading `new` (and `delete`) with their array versions
699// would cause dangerous ambiguity. Consider what would have happened had we
700// overloaded the array version of operator `new`:
701// ```
702// void *operator new[](std::size_t size,
703// BloombergLP::bslma::Allocator& basicAllocator)
704// ```
705// The user of the allocator class may expect to be able to use array
706// `operator new` as follows:
707// ```
708// new (*basicAllocator) my_Type[...];
709// ```
710// The problem is that this expression returns an array that cannot be safely
711// deallocated. On the one hand, there is no syntax in C++ to invoke an
712// overloaded `operator delete` that, other than deallocating memory, would
713// invoke the destructor. On the other hand, the pointer returned by
714// `operator new` cannot be passed to the `deallocate` method directly because
715// the pointer is different from the one returned by the `allocate` method.
716// The compiler offsets the value of this pointer by a header, which is used to
717// maintain the number of objects in the array (so that the non-overloaded
718// `operator delete` can destroy the right number of objects).
719
720/// Return the memory allocated from the specified `basicAllocator` of at
721/// least the specified `size` bytes, or 0 if `size` is 0.
722///
723/// \pre The behavior is undefined unless `0 <= static_cast<bslma::Allocator::size_type>(size)`.
724///
725/// \note Note that an object may allocate additional memory internally, requiring
726/// the allocator to be passed in as a constructor argument:
727/// @code
728/// my_Type *createMyType(bslma::Allocator *basicAllocator)
729/// {
730/// return new (*basicAllocator) my_Type(..., basicAllocator);
731/// }
732/// @endcode
733/// Note also that the analogous version of operator `delete` should *not*
734/// be called directly. Instead, this component provides a template member
735/// function `deleteObject` parameterized by `TYPE` that effectively
736/// performs the following operations:
737/// @code
738/// void deleteMyType(bslma::Allocator *basicAllocator, my_Type *address)
739/// {
740/// address->~my_Type();
741/// basicAllocator->deallocate(address);
742/// }
743/// @endcode
744/// See also `deleteObjectRaw` for better performance when `address` is
745/// known not to be a secondary base type of the object being deleted.
746inline
747void *operator new(std::size_t size,
748 BloombergLP::bslma::Allocator& basicAllocator);
749
750/// Use the specified `basicAllocator` to deallocate the memory at the specified `address`.
751///
752/// \pre The behavior is undefined unless `address` was
753/// allocated using `basicAllocator` and has not already been deallocated.
754/// This operator is supplied solely to allow the compiler to arrange for it
755/// to be called in case of an exception.
756inline
757void operator delete(void *address,
758 BloombergLP::bslma::Allocator& basicAllocator);
759
760// NOTE: The following two operators are declared but never defined to force a
761// link-time error should any code inadvertently use them.
762
763///
764/// \note Note that this operator is intentionally not defined.
765void *operator new(
766 std::size_t size,
767 BloombergLP::bslma::Allocator *basicAllocator) BSLS_KEYWORD_DELETED;
768
769///
770/// \note Note that this operator is intentionally not defined.
771void operator delete(
772 void *address,
773 BloombergLP::bslma::Allocator *basicAllocator) BSLS_KEYWORD_DELETED;
774
775// ============================================================================
776// INLINE DEFINITIONS
777// ============================================================================
778
779
780
781namespace bslma {
782
783 // ---------------
784 // class Allocator
785 // ---------------
786
787// MANIPULATORS
788template <class TYPE>
789inline
790void Allocator::deleteObject(const TYPE *object)
791{
792 DeleterHelper::deleteObject(object, this);
793}
794
795
796inline
798{
799 // This function body is intentionally left blank.
800}
801
802template <class TYPE>
803inline
804void Allocator::deleteObjectRaw(const TYPE *object)
805{
806 DeleterHelper::deleteObjectRaw(object, this);
807}
808
809inline
811{
812 // This function body is intentionally left blank.
813}
814
815} // close package namespace
816
817#ifndef BDE_OPENSOURCE_PUBLICATION
818// ============================================================================
819// BACKWARD COMPATIBILITY
820// ============================================================================
821
822/// These aliases are defined for backward compatibility.
823
824BSLA_DEPRECATED_MESSAGE("Use 'bslma::Allocator' name instead")
825typedef bslma::Allocator bslma_Allocator;
826
827BSLA_DEPRECATED_MESSAGE("Use bslma_allocator component instead")
828typedef bslma::Allocator bdema_Allocator;
829
830#endif // BDE_OPENSOURCE_PUBLICATION
831
832
833
834// ============================================================================
835// INLINE FUNCTION DEFINITIONS
836// ============================================================================
837
838inline
839void *operator new(std::size_t size,
840 BloombergLP::bslma::Allocator& basicAllocator)
841{
842 return basicAllocator.allocate(size);
843}
844
845inline
846void operator delete(void *address,
847 BloombergLP::bslma::Allocator& basicAllocator)
848{
849 basicAllocator.deallocate(address);
850}
851
852#ifdef BSLS_PLATFORM_CMP_MSVC
853template <class t_TYPE,
854 class = typename bsl::enable_if<bsl::is_same<
855 t_TYPE,
856 BloombergLP::bslma::Allocator>::value>::type>
857void *operator new[](std::size_t size, t_TYPE& basicAllocator)
858{
859 BSLMF_ASSERT(sizeof(t_TYPE) == 0);
860 // This assert fires if you have tried to allocate an array using
861 // `operator new[]` with also specifying an allocator (on MSVC). Without
862 // this overload, the Microsoft compiler would just use the non-array
863 // `operator new` and not give an error as other compilers do.
864}
865#endif
866
867#endif
868
869// ----------------------------------------------------------------------------
870// Copyright 2013 Bloomberg Finance L.P.
871//
872// Licensed under the Apache License, Version 2.0 (the "License");
873// you may not use this file except in compliance with the License.
874// You may obtain a copy of the License at
875//
876// http://www.apache.org/licenses/LICENSE-2.0
877//
878// Unless required by applicable law or agreed to in writing, software
879// distributed under the License is distributed on an "AS IS" BASIS,
880// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
881// See the License for the specific language governing permissions and
882// limitations under the License.
883// ----------------------------- END-OF-FILE ----------------------------------
884
885/** @} */
886/** @} */
887/** @} */
Definition bslma_memoryresource.h:443
memory_resource() BSLS_KEYWORD_DEFAULT
Create this object. Has no effect other than to begin its lifetime.
Definition bslma_allocator.h:545
~Allocator() BSLS_KEYWORD_OVERRIDE
void * do_allocate(std::size_t bytes, std::size_t alignment) BSLS_KEYWORD_OVERRIDE
static void throwBadAlloc()
void deleteObjectRaw(const TYPE *object)
Definition bslma_allocator.h:804
virtual void deallocate(void *address)=0
bool do_is_equal(const memory_resource &other) const BSLS_KEYWORD_NOEXCEPT BSLS_KEYWORD_OVERRIDE
std::size_t size_type
Definition bslma_allocator.h:593
void deleteObject(const TYPE *object)
Definition bslma_allocator.h:790
virtual void * allocate(size_type size)=0
void do_deallocate(void *p, std::size_t bytes, std::size_t alignment) BSLS_KEYWORD_OVERRIDE
#define BSLA_DEPRECATED_MESSAGE(message)
Definition bsla_deprecated.h:310
#define BSLMF_ASSERT(expr)
Definition bslmf_assert.h:231
#define BSLS_IDENT(str)
BSLS_IDENT() - insert string into .comment binary segment (if supported)
Definition bsls_ident.h:238
#define BSLS_KEYWORD_DELETED
Definition bsls_keyword.h:651
#define BSLS_KEYWORD_NOEXCEPT
Definition bsls_keyword.h:674
#define BSLS_KEYWORD_OVERRIDE
Definition bsls_keyword.h:695
bsl::size_t size(const TYPE &array)
Return the number of elements in the specified array.
Definition bdlat_valuetypefunctions.h:939
BloombergLP::bsls::Nullptr_Impl::Type nullptr_t
Definition bsls_nullptr.h:283
Definition baljsn_encoder_testtypes.h:76
Definition bdldfp_decimal.h:5549
Definition bslmf_enableif.h:530
Definition bslmf_issame.h:146
static void deleteObject(const TYPE *object, ALLOCATOR *allocator)
Definition bslma_deleterhelper.h:204
static void deleteObjectRaw(const TYPE *object, ALLOCATOR *allocator)
Definition bslma_deleterhelper.h:225