BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bslma_default.h
Go to the documentation of this file.
1/// @file bslma_default.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bslma_default.h -*-C++-*-
8#ifndef INCLUDED_BSLMA_DEFAULT
9#define INCLUDED_BSLMA_DEFAULT
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bslma_default bslma_default
15/// @brief Provide utilities to set/fetch the default and global allocators.
16/// @addtogroup bsl
17/// @{
18/// @addtogroup bslma
19/// @{
20/// @addtogroup bslma_default
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bslma_default-purpose"> Purpose</a>
25/// * <a href="#bslma_default-classes"> Classes </a>
26/// * <a href="#bslma_default-description"> Description </a>
27/// * <a href="#bslma_default-default-allocator"> Default Allocator </a>
28/// * <a href="#bslma_default-global-allocator"> Global Allocator </a>
29/// * <a href="#bslma_default-usage"> Usage </a>
30/// * <a href="#bslma_default-example-1-basic-default-allocator-use"> Example 1: Basic Default Allocator Use </a>
31/// * <a href="#bslma_default-example-2-detecting-allocator-propagation-bugs"> Example 2: Detecting Allocator Propagation Bugs </a>
32/// * <a href="#bslma_default-example-3-basic-global-allocator-use"> Example 3: Basic Global Allocator Use </a>
33///
34/// # Purpose {#bslma_default-purpose}
35/// Provide utilities to set/fetch the default and global allocators.
36///
37/// # Classes {#bslma_default-classes}
38///
39/// - bslma::Default: namespace for default/global allocator management utilities
40///
41/// @see bslma_allocator, bslma_newdeleteallocator
42///
43/// # Description {#bslma_default-description}
44/// This component provides a set of utility functions that manage
45/// the addresses of two distinguished memory allocators: the *default*
46/// allocator and the *global* allocator. Each of these allocators are of type
47/// derived from `bslma::Allocator`. Note that for brevity in the following we
48/// will generally refer to "the address of the default allocator" as simply
49/// "the default allocator" (and similarly for the global allocator).
50///
51/// The global allocator is intended to be used as the allocator for (global)
52/// singleton objects. In general, the default allocator is for all other
53/// memory allocations in contexts where an alternative allocator is not
54/// explicitly specified (or *cannot* be specified as, for example, when a
55/// compiler-generated temporary object of a type that requires an allocator is
56/// created).
57///
58/// Initially, both the default allocator and global allocator resolve to the
59/// address of the `bslma::NewDeleteAllocator` singleton, i.e.:
60/// @code
61/// &bslma::NewDeleteAllocator::singleton()
62/// @endcode
63/// Methods are provided to retrieve and set the two allocators independently.
64/// The following two subsections supply further details, in turn, on the
65/// methods that pertain to the default and global allocators.
66///
67/// ## Default Allocator {#bslma_default-default-allocator}
68///
69///
70/// Two methods provide access to the default allocator,
71/// `bslma::Default::defaultAllocator` and `bslma::Default::allocator` (the
72/// latter when called with no argument, or an explicit 0). When
73/// `bslma::Default::allocator` is supplied with a non-0 argument, it simply
74/// returns that argument to the caller (i.e., it acts as a pass-through). A
75/// (non-singleton) class that is designed to take advantage of an allocator
76/// will typically revert to the default allocator whenever a constructor is
77/// called without an allocator (yielding the default argument value of 0). The
78/// `bslma::Default::allocator` method facilitates this behavior. See the usage
79/// examples below for an illustration of this technique.
80///
81/// The default allocator can be set *prior* to a call to
82/// `bslma::Default::defaultAllocator`, to `bslma::Default::allocator` with no
83/// argument or an explicit 0, or to `bslma::Default::lockDefaultAllocator`, by
84/// calling `bslma::Default::setDefaultAllocator`. This method returns 0 on
85/// success and a non-zero value on failure. This method fails if the default
86/// allocator is "locked". The default allocator is initially unlocked. It is
87/// *explicitly* locked by calling `bslma::Default::lockDefaultAllocator`. In
88/// addition, the default allocator is *implicitly* locked as a *side-effect* of
89/// calling `bslma::Default::defaultAllocator`, or `bslma::Default::allocator`
90/// with no argument or an explicit 0. Once locked, the default allocator
91/// cannot be unlocked. However, the `bslma::Default::setDefaultAllocatorRaw`
92/// method will unconditionally set the default allocator regardless of whether
93/// it is locked. When the C++17 `pmr` library is available, setting the
94/// default allocator by any of these methods also sets the default memory
95/// resource to the same value by invoking `std::pmr::set_default_resource`.
96///
97/// A well-behaved program should call `bslma::Default::setDefaultAllocator`
98/// *once*. It should be invoked in `main` before starting any threads, and be
99/// followed immediately by a call to 'bslma::Default::lockDefaultAllocator.
100/// Note that `bslma::Default::setDefaultAllocatorRaw` is provided for *testing*
101/// *only*, and should typically *never* be used in a production environment.
102///
103/// When using a platform library that supports the C++17 PMR interface, a
104/// successful change to the default allocator will also result in changing the
105/// default *memory* *resource* returned by `std::pmr::get_default_resource` to
106/// the same value. This automatic syncronization can be broken by deliberately
107/// calling `std::pmr::set_default_resource`, which will change the default
108/// memory resource without also changing the default allocator. Note that
109/// `std::pmr::get_default_resource` does not lock the default memory resource
110/// the way `bslma::Default::defaultAllocator` locks the default allocator.
111///
112/// *WARNING*: Note that the default allocator can become locked prior to
113/// entering `main` as a side-effect of initializing a file-scope static object.
114/// For example, the presence of a global `bsl::string` object in an executable
115/// will have this unintended consequence. Further note that this phenomenon
116/// can *vary* *across* *platforms*. In particular, linkers differ as to the
117/// aggressiveness with which they pull in file-scope static objects from the
118/// libraries that are on the link line. *AVOID* file-scope static objects that
119/// require runtime initialization, *especially* those that take an allocator.
120///
121/// ## Global Allocator {#bslma_default-global-allocator}
122///
123///
124/// The interface pertaining to the global allocator is comparatively much
125/// simpler, consisting of just two methods. The
126/// `bslma::Default::globalAllocator` method, when called with no argument (or
127/// an explicit 0), returns the global allocator currently in effect at the
128/// point of call. It has *no* side-effects. When supplied with a non-0
129/// argument, `bslma::Default::globalAllocator` simply returns that argument to
130/// the caller (i.e., it acts as a pass-through similar to
131/// `bslma::Default::allocator` when it is supplied with a non-0 argument). The
132/// global allocator may be set using the `bslma::Default::setGlobalAllocator`
133/// method. This method *always* succeeds. In that respect, the global
134/// allocator cannot become locked like the default allocator.
135/// `bslma::Default::setGlobalAllocator` returns the global allocator that is in
136/// effect upon entry to the function.
137///
138/// Note that `bslma::Default::setGlobalAllocator` should be used with *extreme*
139/// *caution*. In particular, a well-behaved program should call this function
140/// at most once. If called, it should be invoked in `main` before starting any
141/// threads and before initializing singletons.
142///
143/// ## Usage {#bslma_default-usage}
144///
145///
146/// The following sequence of usage examples illustrate recommended use of the
147/// default and global allocators. The examples employ the following simple
148/// memory allocator, `my_CountingAllocator`, that counts both the number of
149/// memory blocks that have been allocated, but not yet deallocated, and the
150/// cumulative number of blocks ever allocated. The two values are available
151/// through the accessors `numBlocksInUse` and `numBlocksTotal`, respectively.
152/// For actual allocations and deallocations, `my_CountingAllocator` uses global
153/// operators `new` and `delete`:
154/// @code
155/// // my_countingallocator.h
156/// #include <bslma_allocator.h>
157///
158/// /// This concrete allocator maintains: (1) a count of the number of
159/// /// blocks allocated that have not yet been deallocated, and (2) a count
160/// /// of the cumulative number of blocks ever allocated.
161/// class my_CountingAllocator : public bslma::Allocator {
162///
163/// // DATA
164/// int d_numBlocksInUse; // number of blocks currently allocated
165/// int d_numBlocksTotal; // cumulative blocks ever requested
166///
167/// // NOT IMPLEMENTED
168/// my_CountingAllocator(const my_CountingAllocator&);
169/// my_CountingAllocator& operator=(const my_CountingAllocator&);
170///
171/// public:
172/// // CREATORS
173///
174/// /// Create a counting allocator.
175/// my_CountingAllocator();
176///
177/// /// Destroy this counting allocator.
178/// virtual ~my_CountingAllocator();
179///
180/// // MANIPULATORS
181///
182/// /// Return a newly allocated block of memory of (at least) the
183/// /// specified positive `size` (bytes). If `size` is 0, a null
184/// /// pointer is returned with no effect. Note that the alignment of
185/// /// the address returned is the maximum alignment for any
186/// /// fundamental type defined for this platform.
187/// virtual void *allocate(size_type size);
188///
189/// /// Return the memory at the specified `address` back to this
190/// /// allocator. If `address` is 0, this function has no effect. The
191/// /// behavior is undefined if `address` was not allocated using this
192/// /// allocator, or has already been deallocated.
193/// virtual void deallocate(void *address);
194///
195/// // ACCESSORS
196///
197/// /// Return the number of blocks currently in use from this counting
198/// /// allocator.
199/// int numBlocksInUse() const;
200///
201/// /// Return the cumulative number of blocks ever allocated using this
202/// /// counting allocator. Note that
203/// /// numBlocksTotal() >= numBlocksInUse().
204/// int numBlocksTotal() const;
205/// };
206///
207/// // CREATORS
208/// inline
209/// my_CountingAllocator::my_CountingAllocator()
210/// : d_numBlocksInUse(0)
211/// , d_numBlocksTotal(0)
212/// {
213/// }
214///
215/// // ACCESSORS
216/// inline
217/// int my_CountingAllocator::numBlocksInUse() const
218/// {
219/// return d_numBlocksInUse;
220/// }
221///
222/// inline
223/// int my_CountingAllocator::numBlocksTotal() const
224/// {
225/// return d_numBlocksTotal;
226/// }
227/// @endcode
228/// The `virtual` methods of `my_CountingAllocator` are defined in the component
229/// `.cpp` file:
230/// @code
231/// // my_countingallocator.cpp
232/// #include <my_countingallocator.h>
233///
234/// // CREATORS
235/// my_CountingAllocator::~my_CountingAllocator()
236/// {
237/// }
238///
239/// // MANIPULATORS
240/// void *my_CountingAllocator::allocate(size_type size)
241/// {
242/// ++d_numBlocksInUse;
243/// ++d_numBlocksTotal;
244/// return ::operator new(size);
245/// }
246///
247/// void my_CountingAllocator::deallocate(void *address)
248/// {
249/// --d_numBlocksInUse;
250/// ::operator delete(address);
251/// }
252/// @endcode
253///
254/// ### Example 1: Basic Default Allocator Use {#bslma_default-example-1-basic-default-allocator-use}
255///
256///
257/// This usage example illustrates the basics of class design that relate to
258/// proper use of the default allocator, and introduces the standard pattern to
259/// apply when setting (and *locking*) the default allocator. First we define a
260/// trivial class, `my_Id`, that uses an allocator. `my_Id` simply encapsulates
261/// a C-style (null-terminated) id string that is accessible through the `id`
262/// method. Note that each constructor is declared to take an *optional*
263/// `bslma::Allocator *` as its last argument. Also note that the expression:
264/// @code
265/// bslma::Default::allocator(basicAllocator)
266/// @endcode
267/// is used in applicable member initializers to propagate each constructor's
268/// allocator argument to the data members that require it (in this case, the
269/// object allocator that is held by each `my_Id` object). If `basicAllocator`
270/// is 0, the object is created using the default allocator. Otherwise, the
271/// explicitly supplied allocator is used:
272/// @code
273/// // my_id.h
274/// #include <bslma_allocator.h>
275/// #include <bslma_default.h>
276///
277/// /// This is a trivial class solely intended to illustrate proper use
278/// /// of the default allocator.
279/// class my_Id {
280///
281/// // DATA
282/// char *d_buffer_p; // allocated (*owned*)
283/// bslma::Allocator *d_allocator_p; // allocator (held, not owned)
284///
285/// // NOT IMPLEMENTED (in order to reduce example size)
286/// my_Id& operator=(const my_Id&);
287///
288/// public:
289/// // CREATORS
290///
291/// /// Create an Id object having the specified `id`. Optionally
292/// /// specify a `basicAllocator` used to supply memory. If
293/// /// `basicAllocator` is 0, the currently installed default allocator
294/// /// is used.
295/// explicit my_Id(const char *id, bslma::Allocator *basicAllocator = 0);
296///
297/// /// Create an Id object initialized to the value of the specified
298/// /// `original` Id object. Optionally specify a `basicAllocator`
299/// /// used to supply memory. If `basicAllocator` is 0, the currently
300/// /// installed default allocator is used.
301/// my_Id(const my_Id& original, bslma::Allocator *basicAllocator = 0);
302///
303/// /// Destroy this Id object.
304/// ~my_Id();
305///
306/// // ACCESSORS
307///
308/// /// Return the id of this Id object.
309/// const char *id() const;
310/// };
311///
312/// // CREATORS
313/// inline
314/// my_Id::my_Id(const char *id, bslma::Allocator *basicAllocator)
315/// : d_allocator_p(bslma::Default::allocator(basicAllocator))
316/// {
317/// d_buffer_p = (char *)d_allocator_p->allocate(std::strlen(id) + 1);
318/// std::strcpy(d_buffer_p, id);
319/// }
320///
321/// inline
322/// my_Id::my_Id(const my_Id& original, bslma::Allocator *basicAllocator)
323/// : d_allocator_p(bslma::Default::allocator(basicAllocator))
324/// {
325/// const char *id = original.id();
326/// d_buffer_p = (char *)d_allocator_p->allocate(std::strlen(id) + 1);
327/// std::strcpy(d_buffer_p, id);
328/// }
329///
330/// inline
331/// my_Id::~my_Id()
332/// {
333/// d_allocator_p->deallocate(d_buffer_p);
334/// }
335///
336/// // ACCESSORS
337/// inline
338/// const char *my_Id::id() const
339/// {
340/// return d_buffer_p;
341/// }
342/// @endcode
343/// Next we set the default allocator to one of our counting allocator objects.
344/// Note that immediately after successfully setting it, we lock the default
345/// allocator, so that subsequent calls to `bslma::Default::setDefaultAllocator`
346/// fail. (The default allocator can still be modified by calling
347/// `bslma::Default::setDefaultAllocatorRaw`, but calling that function in
348/// production code is anti-social. Our usage examples expressly do *not* call
349/// that method.) With the possible exception of test drivers, the default
350/// allocator should be set and locked early in `main` before threads are
351/// started and before objects are initialized:
352/// @code
353/// static my_CountingAllocator defaultCountingAllocator;
354///
355/// int status =
356/// bslma::Default::setDefaultAllocator(&defaultCountingAllocator);
357/// assert(0 == status);
358/// bslma::Default::lockDefaultAllocator(); // subsequent calls to "set" fail
359/// assert(bslma::Default::defaultAllocator() == &defaultCountingAllocator);
360///
361/// status = bslma::Default::setDefaultAllocator(
362/// &bslma::NewDeleteAllocator::singleton());
363/// assert(0 != status);
364/// assert(bslma::Default::defaultAllocator() == &defaultCountingAllocator);
365/// @endcode
366/// In the following, we instantiate two objects of type `my_Id`. The first
367/// object, `idA`, is not supplied with an allocator, so it uses the default
368/// allocator. The second object, `idB`, is supplied with an object of type
369/// `my_CountingAllocator`. The assertions track the states of the two
370/// allocators at each point in the code fragment. In particular, note that the
371/// state of the default allocator does not change during the lifetime of `idB`:
372/// @code
373/// assert(0 == defaultCountingAllocator.numBlocksInUse());
374/// assert(0 == defaultCountingAllocator.numBlocksTotal());
375/// {
376/// my_Id id("A");
377/// assert(1 == defaultCountingAllocator.numBlocksInUse());
378/// assert(1 == defaultCountingAllocator.numBlocksTotal());
379/// }
380/// assert(0 == defaultCountingAllocator.numBlocksInUse());
381/// assert(1 == defaultCountingAllocator.numBlocksTotal());
382///
383/// my_CountingAllocator objectCountingAllocator;
384/// assert(0 == objectCountingAllocator.numBlocksInUse());
385/// assert(0 == objectCountingAllocator.numBlocksTotal());
386/// {
387/// my_Id idB("B", &objectCountingAllocator);
388/// assert(1 == objectCountingAllocator.numBlocksInUse());
389/// assert(1 == objectCountingAllocator.numBlocksTotal());
390/// assert(0 == defaultCountingAllocator.numBlocksInUse());
391/// assert(1 == defaultCountingAllocator.numBlocksTotal());
392/// }
393/// assert(0 == objectCountingAllocator.numBlocksInUse());
394/// assert(1 == objectCountingAllocator.numBlocksTotal());
395/// assert(0 == defaultCountingAllocator.numBlocksInUse());
396/// assert(1 == defaultCountingAllocator.numBlocksTotal());
397/// @endcode
398///
399/// ### Example 2: Detecting Allocator Propagation Bugs {#bslma_default-example-2-detecting-allocator-propagation-bugs}
400///
401///
402/// This example demonstrates how the default allocator is used to detect a very
403/// common programming error pertaining to allocator usage. First we define the
404/// trivial (but buggy) `my_IdPair` class:
405/// @code
406/// // my_idpair.h
407/// #include <my_id.h>
408/// #include <bslma_default.h>
409///
410/// /// This is a trivial class solely intended to help illustrate a common
411/// /// programming error. This class has two objects of type `my_Id`, only
412/// /// one of which has the allocator correctly passed to it in the
413/// /// definition of the constructor.
414/// class my_IdPair {
415///
416/// // DATA
417/// my_Id d_id; // primary id (allocating)
418/// my_Id d_alias; // alias (allocating)
419///
420/// // NOT IMPLEMENTED (in order to reduce example size)
421/// my_IdPair(const my_IdPair&);
422/// my_IdPair& operator=(const my_IdPair&);
423///
424/// public:
425/// // CREATORS
426///
427/// /// Create an Id pair having the specified `id` and `alias` ids.
428/// /// Optionally specify a `basicAllocator` used to supply memory. If
429/// /// `basicAllocator` is 0, the currently installed default allocator
430/// /// is used.
431/// my_IdPair(const char *id,
432/// const char *alias,
433/// bslma::Allocator *basicAllocator = 0);
434///
435/// /// Destroy this Id pair.
436/// ~my_IdPair();
437///
438/// // ACCESSORS
439///
440/// /// Return the primary id of this Id pair.
441/// const char *id() const;
442///
443/// /// Return the alias of this Id pair.
444/// const char *alias() const;
445/// };
446///
447/// // CREATORS
448/// inline
449/// my_IdPair::my_IdPair(const char *id,
450/// const char *alias,
451/// bslma::Allocator *basicAllocator)
452/// : d_id(id, bslma::Default::allocator(basicAllocator))
453/// , d_alias(alias) // drat! (forgot to pass along 'basicAllocator')
454/// {
455/// }
456///
457/// inline
458/// my_IdPair::~my_IdPair()
459/// {
460/// }
461///
462/// // ACCESSORS
463/// inline
464/// const char *my_IdPair::id() const
465/// {
466/// return d_id.id();
467/// }
468///
469/// inline
470/// const char *my_IdPair::alias() const
471/// {
472/// return d_alias.id();
473/// }
474/// @endcode
475/// The definition of the `my_IdPair` constructor above intentionally includes a
476/// common programming error: The allocator in use by the object is not passed
477/// to *all* data members that require it. We will see shortly how this error
478/// is detected at runtime using the default allocator.
479///
480/// Next, the default allocator is set and locked identically to what was done
481/// in usage example 1:
482/// @code
483/// static my_CountingAllocator defaultCountingAllocator;
484///
485/// int status =
486/// bslma::Default::setDefaultAllocator(&defaultCountingAllocator);
487/// assert(0 == status);
488/// bslma::Default::lockDefaultAllocator();
489/// assert(bslma::Default::defaultAllocator() == &defaultCountingAllocator);
490/// @endcode
491/// Now we instantiate an object of type `my_IdPair` without explicitly
492/// specifying an allocator. As a result, the object uses the default
493/// allocator. The assertions verify the expected changes in the state of the
494/// default allocator:
495/// @code
496/// assert(0 == defaultCountingAllocator.numBlocksInUse());
497/// assert(0 == defaultCountingAllocator.numBlocksTotal());
498/// {
499/// my_IdPair idPair("A", "B");
500/// assert(2 == defaultCountingAllocator.numBlocksInUse());
501/// assert(2 == defaultCountingAllocator.numBlocksTotal());
502/// }
503/// assert(0 == defaultCountingAllocator.numBlocksInUse());
504/// assert(2 == defaultCountingAllocator.numBlocksTotal());
505/// @endcode
506/// Next we instantiate a second object of type `my_IdPair`, this time supplying
507/// it with a counting allocator object that is distinct from the default
508/// allocator. The assertions in the following code fragment that are commented
509/// out indicate the *expected* states of the allocators (i.e., in a bug-free
510/// implementation of `my_IdPair`) after the object has been constructed and
511/// again after it has been destroyed. However, due to the (intentional) bug in
512/// the constructor, the uncommented assertions reveal the *true* state of
513/// affairs:
514/// @code
515/// my_CountingAllocator objectCountingAllocator;
516/// assert(0 == objectCountingAllocator.numBlocksInUse());
517/// assert(0 == objectCountingAllocator.numBlocksTotal());
518/// {
519/// my_IdPair idPair("X", "Y", &objectCountingAllocator);
520/// // assert(2 == objectCountingAllocator.numBlocksInUse());
521/// // assert(2 == objectCountingAllocator.numBlocksTotal());
522/// // assert(0 == defaultCountingAllocator.numBlocksInUse());
523/// // assert(2 == defaultCountingAllocator.numBlocksTotal());
524/// assert(1 == objectCountingAllocator.numBlocksInUse());
525/// assert(1 == objectCountingAllocator.numBlocksTotal());
526/// assert(1 == defaultCountingAllocator.numBlocksInUse());
527/// assert(3 == defaultCountingAllocator.numBlocksTotal());
528/// }
529/// // assert(0 == objectCountingAllocator.numBlocksInUse());
530/// // assert(2 == objectCountingAllocator.numBlocksTotal());
531/// // assert(0 == defaultCountingAllocator.numBlocksInUse());
532/// // assert(2 == defaultCountingAllocator.numBlocksTotal());
533/// assert(0 == objectCountingAllocator.numBlocksInUse());
534/// assert(1 == objectCountingAllocator.numBlocksTotal());
535/// assert(0 == defaultCountingAllocator.numBlocksInUse());
536/// assert(3 == defaultCountingAllocator.numBlocksTotal());
537/// @endcode
538/// Note that, although not necessary in the case of the simple `my_IdPair`
539/// class, the default allocator can be used (and typically *should* be used)
540/// within the body of a constructor, or any other member function, to allocate
541/// dynamic memory that is *temporarily* needed by the method (and, hence, not
542/// owned by the object after the method has returned). Thus, the invariant
543/// that must hold immediately after a method of an object returns is that the
544/// value returned by `defaultCountingAllocator.numBlocksInUse()` must be
545/// *identical* to what it was immediately prior to calling the method. Of
546/// course, note that the above invariant pertains to cases in *single*-threaded
547/// programs where the object allocator in use by the object is *distinct* from
548/// the default allocator. Also note that the value returned by
549/// `defaultCountingAllocator.numBlocksTotal()` *can* differ across function
550/// invocations (i.e., even in correct code).
551///
552/// ### Example 3: Basic Global Allocator Use {#bslma_default-example-3-basic-global-allocator-use}
553///
554///
555/// Next we define a simple singleton class, `my_Singleton`, that defaults to
556/// using the global allocator if one is not explicitly specified when the
557/// singleton object is initialized. Toward that end, note that in contrast to
558/// `my_Id`, the constructor for `my_Singleton` uses:
559/// @code
560/// bslma::Default::globalAllocator(basicAllocator)
561/// @endcode
562/// in its member initializer:
563/// @code
564/// // my_singleton.h
565///
566/// /// This is a trivial singleton class solely intended to illustrate use
567/// /// of the global allocator.
568/// class my_Singleton {
569///
570/// // CLASS DATA
571/// static my_Singleton *s_singleton_p; // pointer to singleton object
572///
573/// // PRIVATE DATA
574/// my_Id d_id; // allocating
575///
576/// // NOT IMPLEMENTED
577/// my_Singleton(const my_Singleton& original,
578/// bslma::Allocator *basicAllocator = 0);
579/// my_Singleton& operator=(const my_Singleton& rhs);
580///
581/// private:
582/// // PRIVATE CREATORS
583///
584/// /// Create a singleton having the specified `id`. Optionally
585/// /// specify a `basicAllocator` used to supply memory. If
586/// /// `basicAllocator` is 0, the currently installed global allocator
587/// /// is used.
588/// explicit my_Singleton(const char *id,
589/// bslma::Allocator *basicAllocator = 0);
590///
591/// /// Destroy this singleton.
592/// ~my_Singleton();
593///
594/// public:
595/// // CLASS METHODS
596///
597/// /// Initialize the singleton with the specified `id`. Optionally
598/// /// specify a `basicAllocator` used to supply memory. If
599/// /// `basicAllocator` is 0, the currently installed global allocator
600/// /// is used.
601/// static void initSingleton(const char *id,
602/// bslma::Allocator *basicAllocator = 0);
603///
604/// /// Return a reference to the non-modifiable singleton of this
605/// /// class. The behavior is undefined unless the singleton has been
606/// /// initialized.
607/// static const my_Singleton& singleton();
608///
609/// // ACCESSORS
610///
611/// /// Return the id of this singleton.
612/// const char *id() const;
613/// };
614///
615/// // CLASS METHODS
616/// inline
617/// const my_Singleton& my_Singleton::singleton()
618/// {
619/// return *s_singleton_p;
620/// }
621///
622/// // CREATORS
623/// inline
624/// my_Singleton::my_Singleton(const char *id,
625/// bslma::Allocator *basicAllocator)
626/// : d_id(id, bslma::Default::globalAllocator(basicAllocator))
627/// {
628/// }
629///
630/// inline
631/// my_Singleton::~my_Singleton()
632/// {
633/// }
634///
635/// // ACCESSORS
636/// inline
637/// const char *my_Singleton::id() const
638/// {
639/// return d_id.id();
640/// }
641/// @endcode
642/// The following completes the definition of `my_Singleton` in the component
643/// `.cpp` file:
644/// @code
645/// // my_singleton.cpp
646/// #include <my_singleton.h>
647/// #include <bsls_alignedbuffer.h>
648///
649/// my_Singleton *my_Singleton::s_singleton_p;
650///
651/// // CLASS METHODS
652/// void my_Singleton::initSingleton(const char *id,
653/// bslma::Allocator *basicAllocator)
654/// {
655/// static bsls::AlignedBuffer<sizeof(my_Singleton)> singleton;
656/// s_singleton_p = new (singleton.buffer()) my_Singleton(id,
657/// basicAllocator);
658/// }
659/// @endcode
660/// In the following, the default and global allocators are set to distinct
661/// instances of `my_CountingAllocator`. Note that the default allocator is set
662/// and locked identically to what was done in the previous two usage examples:
663/// @code
664/// static my_CountingAllocator defaultCountingAllocator;
665///
666/// int status = bslma::Default::setDefaultAllocator(
667/// &defaultCountingAllocator);
668/// assert(0 == status);
669/// bslma::Default::lockDefaultAllocator();
670/// assert(bslma::Default::defaultAllocator() == &defaultCountingAllocator);
671///
672/// static my_CountingAllocator globalCountingAllocator;
673///
674/// bslma::Default::setGlobalAllocator(&globalCountingAllocator);
675/// assert(bslma::Default::globalAllocator() == &globalCountingAllocator);
676/// @endcode
677/// Finally, we initialize the singleton object. We explicitly specify the
678/// desired allocator in the call to `initSingleton` to make our intentions as
679/// clear as possible. Of course, because of the way the `my_Singleton`
680/// constructor was written, the result would have been the same if no allocator
681/// had been specified. As in previous examples, the states of the default and
682/// global allocators are asserted before and after initializing the singleton:
683/// @code
684/// assert(0 == defaultCountingAllocator.numBlocksInUse());
685/// assert(0 == defaultCountingAllocator.numBlocksTotal());
686/// assert(0 == globalCountingAllocator.numBlocksInUse());
687/// assert(0 == globalCountingAllocator.numBlocksTotal());
688///
689/// my_Singleton::initSingleton("S", bslma::Default::globalAllocator());
690///
691/// assert(0 == defaultCountingAllocator.numBlocksInUse());
692/// assert(0 == defaultCountingAllocator.numBlocksTotal());
693/// assert(1 == globalCountingAllocator.numBlocksInUse());
694/// assert(1 == globalCountingAllocator.numBlocksTotal());
695/// @endcode
696/// @}
697/** @} */
698/** @} */
699
700/** @addtogroup bsl
701 * @{
702 */
703/** @addtogroup bslma
704 * @{
705 */
706/** @addtogroup bslma_default
707 * @{
708 */
709
710#include <bslscm_version.h>
711
713
714#include <bslma_allocator.h>
716
717
718
719namespace bslma {
720
721 // ==============
722 // struct Default
723 // ==============
724
725/// This struct is a mechanism with global state, i.e., all state is held in
726/// global variables and all functions are class methods. The state
727/// consists of two distinct parts that don't influence one another: the
728/// default allocator and the global allocator. All addresses are stored
729/// without assuming ownership.
730///
731/// The `setDefaultAllocator` method will only modify the default allocator
732/// prior to the default allocator being accessed (by either `allocator`,
733/// `defaultAllocator`, or `lockDefaultAllocator`). The global allocator may
734/// be freely modified.
735///
736/// Note that *only* the *owner* of `main` (or in *testing*), where the
737/// caller affirmatively takes responsibility for the behavior of all
738/// clients of the global allocator, is intended to change the global
739/// allocator.
740struct Default {
741
742 private:
743 // CLASS DATA
744
745 // *** default allocator ***
746
747 /// The default allocator that is requested by the user and will be
748 /// installed as the default allocator on the first attempt to access
749 /// the default allocator (via `allocator`, `defaultAllocator`, or
750 /// `lockDefaultAllocator`). This value is initialized to `0`,
751 /// indicating the user hasn't made a choice yet. In that case, when
752 /// needed, the new-delete allocator will be used. This value can be
753 /// set (multiple times) by calling to `setDefaultAllocator`. Note that
754 /// once changed this variable will not become `0` again.
755 static bsls::AtomicOperations::AtomicTypes::Pointer
756 s_requestedDefaultAllocator;
757
758 /// The currently installed default allocator. This variable must be
759 /// set only once, when the default allocator is first accessed (via
760 /// `allocator`, `defaultAllocator`, or `lockDefaultAllocator`) but may
761 /// be `0` before it is accessed unless *for* *testing* *only*
762 /// `setDefaultAllocatorRaw` is used.
763 static bsls::AtomicOperations::AtomicTypes::Pointer s_defaultAllocator;
764
765 // *** global allocator ***
766
767 /// The address of the global allocator to use.
768 static bsls::AtomicOperations::AtomicTypes::Pointer s_globalAllocator;
769
770 // PRIVATE CLASS METHODS
771
772 /// Return the address of the default allocator and disable all
773 /// subsequent calls to the `setDefaultAllocator` method. If
774 /// `s_defaultAllocator` is 0 (meaning the default allocator has not yet
775 /// been accessed), set it to the last value supplied to
776 /// `setDefaultAllocator` (stored in `s_requestedDefaultAllocator`). If
777 /// `s_requestedDefaultAllocator` is 0 (meaning `setDefaultAllocator`
778 /// has not been called) set `s_defaultAllocator` and
779 /// `s_requestedDefaultAllocator` to be the new-delete allocator. Note
780 /// that this operation performs the one and only assigment to
781 /// `s_defaultAllocator` (unless `setDefaultAllocatorRaw` is called).
782 /// In C++, this function also ensures that the default
783 /// `std::pmr::memory_resource` is the same as the default `Allocator`.
784 /// Note also that this function has the same externally visible
785 /// behavior as `defaultAllocator`, but forms the (thread-safe)
786 /// "slow-path" for that function's implementation.
787 static Allocator *determineAndReturnDefaultAllocator();
788
789 public:
790 // CLASS METHODS
791
792 // *** default allocator ***
793
794 /// Set the address of the default allocator to the specified
795 /// `basicAllocator` unless calls to this method have been disabled.
796 /// Return 0 on success and a non-zero value otherwise. This method
797 /// will fail if either `defaultAllocator`, `lockDefaultAllocator`, or
798 /// `allocator` with argument 0 has been called previously in this
799 /// process. In C++17 and later, a successful call to this method will
800 /// also set the default `std::pmr::memory_resource`. The behavior is
801 /// undefined unless `basicAllocator` is the address of an allocator
802 /// with sufficient lifetime to satisfy all allocation requests within
803 /// this process, and unless there is only one thread started within
804 /// this process. Note that this method is intended for use *only* by
805 /// the *owner* of `main` (or for use in *testing*) where the caller
806 /// affirmatively takes responsibility for the behavior of all clients
807 /// of the default allocator, and should *not* be used for any other
808 /// purpose.
809 static int setDefaultAllocator(Allocator *basicAllocator);
810
811 /// Unconditionally set the address of the default allocator to the
812 /// specified `basicAllocator`. In C++17 and later, a call to this
813 /// method will also set the default `std::pmr::memory_resource`. The
814 /// behavior is undefined unless `basicAllocator` is the address of an
815 /// allocator with sufficient lifetime to satisfy all allocation
816 /// requests within this process, and unless there is only one thread
817 /// started within this process. Note that this method is intended for
818 /// use *only* in *testing* where the caller affirmatively takes
819 /// responsibility for the behavior of all clients of the default
820 /// allocator, and should *not* be used for any other purpose.
821 static void setDefaultAllocatorRaw(Allocator *basicAllocator);
822
823 /// Disable all subsequent calls to the `setDefaultAllocator` method.
824 /// Subsequent calls to this method have no effect. Note that
825 /// subsequent calls to the `setDefaultAllocatorRaw` method are *not*
826 /// disabled by this method.
827 static void lockDefaultAllocator();
828
829 /// Return the address of the default allocator and disable all
830 /// subsequent calls to the `setDefaultAllocator` method. Note that
831 /// prior to the first call to `setDefaultAllocator` or
832 /// `setDefaultAllocatorRaw` methods, the address of the default
833 /// allocator is that of the `NewDeleteAllocator` singleton. Also note
834 /// that subsequent calls to `setDefaultAllocatorRaw` method are *not*
835 /// disabled by this method.
836 static Allocator *defaultAllocator();
837
838 /// Return the allocator returned by `defaultAllocator` and disable all
839 /// subsequent calls to the `setDefaultAllocator` method if the
840 /// optionally-specified `basicAllocator` is 0; return `basicAllocator`
841 /// otherwise.
842 static Allocator *allocator(Allocator *basicAllocator = 0);
843
844 // *** global allocator ***
845
846 /// Return the address of the global allocator if the optionally-
847 /// specified `basicAllocator` is 0, and `basicAllocator` otherwise.
848 /// Note that prior to the first call to the `setGlobalAllocator`
849 /// method, the address of the global allocator is that of the
850 /// `NewDeleteAllocator` singleton.
851 static Allocator *globalAllocator(Allocator *basicAllocator = 0);
852
853 /// Unconditionally set the address of the global allocator to the
854 /// specified `basicAllocator`, or to the address of the
855 /// `NewDeleteAllocator` singleton if `basicAllocator` is 0. Return the
856 /// address of the global allocator in effect immediately before calling
857 /// this method. The behavior is undefined unless `basicAllocator` is 0
858 /// or is the address of an allocator with sufficient lifetime to
859 /// satisfy all global allocation requests within this process, and
860 /// unless there is only one thread started within this process. Note
861 /// that prior to the first call to this method, the address of the
862 /// global allocator is that of the `NewDeleteAllocator` singleton.
863 /// Also note that this method is intended for use *only* by the *owner*
864 /// of `main` (or for use in *testing*) where the caller affirmatively
865 /// takes responsibility for the behavior of all clients of the global
866 /// allocator, and should *not* be used for any other purpose.
867 static Allocator *setGlobalAllocator(Allocator *basicAllocator);
868};
869
870// ============================================================================
871// INLINE FUNCTION DEFINITIONS
872// ============================================================================
873
874 // --------------
875 // struct Default
876 // --------------
877
878// CLASS METHODS
879
880 // *** default allocator ***
881
882inline
884{
885 determineAndReturnDefaultAllocator();
886}
887
888inline
890{
891 void *alloc = bsls::AtomicOperations::getPtrRelaxed(&s_defaultAllocator);
892 return alloc ? static_cast<Allocator *>(alloc)
893 : determineAndReturnDefaultAllocator();
894}
895
896inline
898{
899 return basicAllocator ? basicAllocator : defaultAllocator();
900}
901
902 // *** global allocator ***
903
904inline
906{
907 Allocator *globalAllocator = static_cast<Allocator *>(const_cast<void *>(
908 bsls::AtomicOperations::getPtrAcquire(&s_globalAllocator)));
909
910 return basicAllocator ? basicAllocator
914}
915
916#ifdef BSLS_LIBRARYFEATURES_HAS_CPP17_PMR
917
918/// Stateless class to set the initial default resource to
919/// `bslma::NewDeleteAllocator` automatically when using this component
920/// with a platform that supports C++17 `std::pmr::memory_resource`.
921struct Default_NewDeleteSetter {
922
923 /// If `std::pmr::set_default_resource` has not yet been invoked, call
924 /// it with the address of the `bslma::NewDeleteAllocator` singleton,
925 /// thus ensuring that `bslma::Default` and `get_default_resource` are
926 /// in sync.
927 Default_NewDeleteSetter();
928
929 Default_NewDeleteSetter(const Default_NewDeleteSetter&) = delete;
930};
931
932/// Static initialization of this variable ensures that the default resource
933/// is set to `NewDeleteAllocator` before it is read by other code.
934static Default_NewDeleteSetter Default_NewDeleteSetterSingleton;
935
936#endif // BSLS_LIBRARYFEATURES_HAS_CPP17_PMR
937
938} // close package namespace
939
940#ifndef BDE_OPENSOURCE_PUBLICATION // BACKWARD_COMPATIBILITY
941
942// ============================================================================
943// BACKWARD COMPATIBILITY
944// ============================================================================
945
946#ifndef BDE_OMIT_INTERNAL_DEPRECATED
947 // ====================
948 // struct bdema_Default
949 // ====================
950
951/// This `struct` is a namespace for functions that manipulate and access
952/// the default and global allocator pointers. This alias is defined for
953/// backward compatibility.
955
956#endif // BDE_OMIT_INTERNAL_DEPRECATED
957
958/// This alias is defined for backward compatibility.
960
961#endif // BDE_OPENSOURCE_PUBLICATION -- BACKWARD_COMPATIBILITY
962
963
964
965#endif
966
967// ----------------------------------------------------------------------------
968// Copyright 2013 Bloomberg Finance L.P.
969//
970// Licensed under the Apache License, Version 2.0 (the "License");
971// you may not use this file except in compliance with the License.
972// You may obtain a copy of the License at
973//
974// http://www.apache.org/licenses/LICENSE-2.0
975//
976// Unless required by applicable law or agreed to in writing, software
977// distributed under the License is distributed on an "AS IS" BASIS,
978// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
979// See the License for the specific language governing permissions and
980// limitations under the License.
981// ----------------------------- END-OF-FILE ----------------------------------
982
983/** @} */
984/** @} */
985/** @} */
Definition bslma_allocator.h:457
static NewDeleteAllocator & singleton()
bslma::Default bslma_Default
This alias is defined for backward compatibility.
Definition bslma_default.h:959
bslma::Default bdema_Default
Definition bslma_default.h:954
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
Definition balxml_encoderoptions.h:68
Definition bslma_default.h:740
static Allocator * globalAllocator(Allocator *basicAllocator=0)
Definition bslma_default.h:905
static Allocator * setGlobalAllocator(Allocator *basicAllocator)
static Allocator * allocator(Allocator *basicAllocator=0)
Definition bslma_default.h:897
static void setDefaultAllocatorRaw(Allocator *basicAllocator)
static void lockDefaultAllocator()
Definition bslma_default.h:883
static int setDefaultAllocator(Allocator *basicAllocator)
static Allocator * defaultAllocator()
Definition bslma_default.h:889
static void * getPtrAcquire(AtomicTypes::Pointer const *atomicPtr)
Definition bsls_atomicoperations.h:2312
static void * getPtrRelaxed(AtomicTypes::Pointer const *atomicPtr)
Definition bsls_atomicoperations.h:2318