BDE 4.39.x 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/// private:
168/// // NOT IMPLEMENTED
169/// my_CountingAllocator(const my_CountingAllocator&);
170/// my_CountingAllocator& operator=(const my_CountingAllocator&);
171///
172/// public:
173/// // CREATORS
174///
175/// /// Create a counting allocator.
176/// my_CountingAllocator();
177///
178/// /// Destroy this counting allocator.
179/// virtual ~my_CountingAllocator();
180///
181/// // MANIPULATORS
182///
183/// /// Return a newly allocated block of memory of (at least) the
184/// /// specified positive `size` (bytes). If `size` is 0, a null
185/// /// pointer is returned with no effect. Note that the alignment of
186/// /// the address returned is the maximum alignment for any
187/// /// fundamental type defined for this platform.
188/// virtual void *allocate(size_type size);
189///
190/// /// Return the memory at the specified `address` back to this
191/// /// allocator. If `address` is 0, this function has no effect. The
192/// /// behavior is undefined if `address` was not allocated using this
193/// /// allocator, or has already been deallocated.
194/// virtual void deallocate(void *address);
195///
196/// // ACCESSORS
197///
198/// /// Return the number of blocks currently in use from this counting
199/// /// allocator.
200/// int numBlocksInUse() const;
201///
202/// /// Return the cumulative number of blocks ever allocated using this
203/// /// counting allocator. Note that
204/// /// numBlocksTotal() >= numBlocksInUse().
205/// int numBlocksTotal() const;
206/// };
207///
208/// // CREATORS
209/// inline
210/// my_CountingAllocator::my_CountingAllocator()
211/// : d_numBlocksInUse(0)
212/// , d_numBlocksTotal(0)
213/// {
214/// }
215///
216/// // ACCESSORS
217/// inline
218/// int my_CountingAllocator::numBlocksInUse() const
219/// {
220/// return d_numBlocksInUse;
221/// }
222///
223/// inline
224/// int my_CountingAllocator::numBlocksTotal() const
225/// {
226/// return d_numBlocksTotal;
227/// }
228/// @endcode
229/// The `virtual` methods of `my_CountingAllocator` are defined in the component
230/// `.cpp` file:
231/// @code
232/// // my_countingallocator.cpp
233/// #include <my_countingallocator.h>
234///
235/// // CREATORS
236/// my_CountingAllocator::~my_CountingAllocator()
237/// {
238/// }
239///
240/// // MANIPULATORS
241/// void *my_CountingAllocator::allocate(size_type size)
242/// {
243/// ++d_numBlocksInUse;
244/// ++d_numBlocksTotal;
245/// return ::operator new(size);
246/// }
247///
248/// void my_CountingAllocator::deallocate(void *address)
249/// {
250/// --d_numBlocksInUse;
251/// ::operator delete(address);
252/// }
253/// @endcode
254///
255/// ### Example 1: Basic Default Allocator Use {#bslma_default-example-1-basic-default-allocator-use}
256///
257///
258/// This usage example illustrates the basics of class design that relate to
259/// proper use of the default allocator, and introduces the standard pattern to
260/// apply when setting (and *locking*) the default allocator. First we define a
261/// trivial class, `my_Id`, that uses an allocator. `my_Id` simply encapsulates
262/// a C-style (null-terminated) id string that is accessible through the `id`
263/// method. Note that each constructor is declared to take an *optional*
264/// `bslma::Allocator *` as its last argument. Also note that the expression:
265/// @code
266/// bslma::Default::allocator(basicAllocator)
267/// @endcode
268/// is used in applicable member initializers to propagate each constructor's
269/// allocator argument to the data members that require it (in this case, the
270/// object allocator that is held by each `my_Id` object). If `basicAllocator`
271/// is 0, the object is created using the default allocator. Otherwise, the
272/// explicitly supplied allocator is used:
273/// @code
274/// // my_id.h
275/// #include <bslma_allocator.h>
276/// #include <bslma_default.h>
277///
278/// /// This is a trivial class solely intended to illustrate proper use
279/// /// of the default allocator.
280/// class my_Id {
281///
282/// // DATA
283/// char *d_buffer_p; // allocated (*owned*)
284/// bslma::Allocator *d_allocator_p; // allocator (held, not owned)
285///
286/// // NOT IMPLEMENTED (in order to reduce example size)
287/// my_Id& operator=(const my_Id&);
288///
289/// public:
290/// // CREATORS
291///
292/// /// Create an Id object having the specified `id`. Optionally
293/// /// specify a `basicAllocator` used to supply memory. If
294/// /// `basicAllocator` is 0, the currently installed default allocator
295/// /// is used.
296/// explicit my_Id(const char *id, bslma::Allocator *basicAllocator = 0);
297///
298/// /// Create an Id object initialized to the value of the specified
299/// /// `original` Id object. Optionally specify a `basicAllocator`
300/// /// used to supply memory. If `basicAllocator` is 0, the currently
301/// /// installed default allocator is used.
302/// my_Id(const my_Id& original, bslma::Allocator *basicAllocator = 0);
303///
304/// /// Destroy this Id object.
305/// ~my_Id();
306///
307/// // ACCESSORS
308///
309/// /// Return the id of this Id object.
310/// const char *id() const;
311/// };
312///
313/// // CREATORS
314/// inline
315/// my_Id::my_Id(const char *id, bslma::Allocator *basicAllocator)
316/// : d_allocator_p(bslma::Default::allocator(basicAllocator))
317/// {
318/// d_buffer_p = (char *)d_allocator_p->allocate(std::strlen(id) + 1);
319/// std::strcpy(d_buffer_p, id);
320/// }
321///
322/// inline
323/// my_Id::my_Id(const my_Id& original, bslma::Allocator *basicAllocator)
324/// : d_allocator_p(bslma::Default::allocator(basicAllocator))
325/// {
326/// const char *id = original.id();
327/// d_buffer_p = (char *)d_allocator_p->allocate(std::strlen(id) + 1);
328/// std::strcpy(d_buffer_p, id);
329/// }
330///
331/// inline
332/// my_Id::~my_Id()
333/// {
334/// d_allocator_p->deallocate(d_buffer_p);
335/// }
336///
337/// // ACCESSORS
338/// inline
339/// const char *my_Id::id() const
340/// {
341/// return d_buffer_p;
342/// }
343/// @endcode
344/// Next we set the default allocator to one of our counting allocator objects.
345/// Note that immediately after successfully setting it, we lock the default
346/// allocator, so that subsequent calls to `bslma::Default::setDefaultAllocator`
347/// fail. (The default allocator can still be modified by calling
348/// `bslma::Default::setDefaultAllocatorRaw`, but calling that function in
349/// production code is anti-social. Our usage examples expressly do *not* call
350/// that method.) With the possible exception of test drivers, the default
351/// allocator should be set and locked early in `main` before threads are
352/// started and before objects are initialized:
353/// @code
354/// static my_CountingAllocator defaultCountingAllocator;
355///
356/// int status =
357/// bslma::Default::setDefaultAllocator(&defaultCountingAllocator);
358/// assert(0 == status);
359/// bslma::Default::lockDefaultAllocator(); // subsequent calls to "set" fail
360/// assert(bslma::Default::defaultAllocator() == &defaultCountingAllocator);
361///
362/// status = bslma::Default::setDefaultAllocator(
363/// &bslma::NewDeleteAllocator::singleton());
364/// assert(0 != status);
365/// assert(bslma::Default::defaultAllocator() == &defaultCountingAllocator);
366/// @endcode
367/// In the following, we instantiate two objects of type `my_Id`. The first
368/// object, `idA`, is not supplied with an allocator, so it uses the default
369/// allocator. The second object, `idB`, is supplied with an object of type
370/// `my_CountingAllocator`. The assertions track the states of the two
371/// allocators at each point in the code fragment. In particular, note that the
372/// state of the default allocator does not change during the lifetime of `idB`:
373/// @code
374/// assert(0 == defaultCountingAllocator.numBlocksInUse());
375/// assert(0 == defaultCountingAllocator.numBlocksTotal());
376/// {
377/// my_Id id("A");
378/// assert(1 == defaultCountingAllocator.numBlocksInUse());
379/// assert(1 == defaultCountingAllocator.numBlocksTotal());
380/// }
381/// assert(0 == defaultCountingAllocator.numBlocksInUse());
382/// assert(1 == defaultCountingAllocator.numBlocksTotal());
383///
384/// my_CountingAllocator objectCountingAllocator;
385/// assert(0 == objectCountingAllocator.numBlocksInUse());
386/// assert(0 == objectCountingAllocator.numBlocksTotal());
387/// {
388/// my_Id idB("B", &objectCountingAllocator);
389/// assert(1 == objectCountingAllocator.numBlocksInUse());
390/// assert(1 == objectCountingAllocator.numBlocksTotal());
391/// assert(0 == defaultCountingAllocator.numBlocksInUse());
392/// assert(1 == defaultCountingAllocator.numBlocksTotal());
393/// }
394/// assert(0 == objectCountingAllocator.numBlocksInUse());
395/// assert(1 == objectCountingAllocator.numBlocksTotal());
396/// assert(0 == defaultCountingAllocator.numBlocksInUse());
397/// assert(1 == defaultCountingAllocator.numBlocksTotal());
398/// @endcode
399///
400/// ### Example 2: Detecting Allocator Propagation Bugs {#bslma_default-example-2-detecting-allocator-propagation-bugs}
401///
402///
403/// This example demonstrates how the default allocator is used to detect a very
404/// common programming error pertaining to allocator usage. First we define the
405/// trivial (but buggy) `my_IdPair` class:
406/// @code
407/// // my_idpair.h
408/// #include <my_id.h>
409/// #include <bslma_default.h>
410///
411/// /// This is a trivial class solely intended to help illustrate a common
412/// /// programming error. This class has two objects of type `my_Id`, only
413/// /// one of which has the allocator correctly passed to it in the
414/// /// definition of the constructor.
415/// class my_IdPair {
416///
417/// // DATA
418/// my_Id d_id; // primary id (allocating)
419/// my_Id d_alias; // alias (allocating)
420///
421/// // NOT IMPLEMENTED (in order to reduce example size)
422/// my_IdPair(const my_IdPair&);
423/// my_IdPair& operator=(const my_IdPair&);
424///
425/// public:
426/// // CREATORS
427///
428/// /// Create an Id pair having the specified `id` and `alias` ids.
429/// /// Optionally specify a `basicAllocator` used to supply memory. If
430/// /// `basicAllocator` is 0, the currently installed default allocator
431/// /// is used.
432/// my_IdPair(const char *id,
433/// const char *alias,
434/// bslma::Allocator *basicAllocator = 0);
435///
436/// /// Destroy this Id pair.
437/// ~my_IdPair();
438///
439/// // ACCESSORS
440///
441/// /// Return the primary id of this Id pair.
442/// const char *id() const;
443///
444/// /// Return the alias of this Id pair.
445/// const char *alias() const;
446/// };
447///
448/// // CREATORS
449/// inline
450/// my_IdPair::my_IdPair(const char *id,
451/// const char *alias,
452/// bslma::Allocator *basicAllocator)
453/// : d_id(id, bslma::Default::allocator(basicAllocator))
454/// , d_alias(alias) // drat! (forgot to pass along 'basicAllocator')
455/// {
456/// }
457///
458/// inline
459/// my_IdPair::~my_IdPair()
460/// {
461/// }
462///
463/// // ACCESSORS
464/// inline
465/// const char *my_IdPair::id() const
466/// {
467/// return d_id.id();
468/// }
469///
470/// inline
471/// const char *my_IdPair::alias() const
472/// {
473/// return d_alias.id();
474/// }
475/// @endcode
476/// The definition of the `my_IdPair` constructor above intentionally includes a
477/// common programming error: The allocator in use by the object is not passed
478/// to *all* data members that require it. We will see shortly how this error
479/// is detected at runtime using the default allocator.
480///
481/// Next, the default allocator is set and locked identically to what was done
482/// in usage example 1:
483/// @code
484/// static my_CountingAllocator defaultCountingAllocator;
485///
486/// int status =
487/// bslma::Default::setDefaultAllocator(&defaultCountingAllocator);
488/// assert(0 == status);
489/// bslma::Default::lockDefaultAllocator();
490/// assert(bslma::Default::defaultAllocator() == &defaultCountingAllocator);
491/// @endcode
492/// Now we instantiate an object of type `my_IdPair` without explicitly
493/// specifying an allocator. As a result, the object uses the default
494/// allocator. The assertions verify the expected changes in the state of the
495/// default allocator:
496/// @code
497/// assert(0 == defaultCountingAllocator.numBlocksInUse());
498/// assert(0 == defaultCountingAllocator.numBlocksTotal());
499/// {
500/// my_IdPair idPair("A", "B");
501/// assert(2 == defaultCountingAllocator.numBlocksInUse());
502/// assert(2 == defaultCountingAllocator.numBlocksTotal());
503/// }
504/// assert(0 == defaultCountingAllocator.numBlocksInUse());
505/// assert(2 == defaultCountingAllocator.numBlocksTotal());
506/// @endcode
507/// Next we instantiate a second object of type `my_IdPair`, this time supplying
508/// it with a counting allocator object that is distinct from the default
509/// allocator. The assertions in the following code fragment that are commented
510/// out indicate the *expected* states of the allocators (i.e., in a bug-free
511/// implementation of `my_IdPair`) after the object has been constructed and
512/// again after it has been destroyed. However, due to the (intentional) bug in
513/// the constructor, the uncommented assertions reveal the *true* state of
514/// affairs:
515/// @code
516/// my_CountingAllocator objectCountingAllocator;
517/// assert(0 == objectCountingAllocator.numBlocksInUse());
518/// assert(0 == objectCountingAllocator.numBlocksTotal());
519/// {
520/// my_IdPair idPair("X", "Y", &objectCountingAllocator);
521/// // assert(2 == objectCountingAllocator.numBlocksInUse());
522/// // assert(2 == objectCountingAllocator.numBlocksTotal());
523/// // assert(0 == defaultCountingAllocator.numBlocksInUse());
524/// // assert(2 == defaultCountingAllocator.numBlocksTotal());
525/// assert(1 == objectCountingAllocator.numBlocksInUse());
526/// assert(1 == objectCountingAllocator.numBlocksTotal());
527/// assert(1 == defaultCountingAllocator.numBlocksInUse());
528/// assert(3 == defaultCountingAllocator.numBlocksTotal());
529/// }
530/// // assert(0 == objectCountingAllocator.numBlocksInUse());
531/// // assert(2 == objectCountingAllocator.numBlocksTotal());
532/// // assert(0 == defaultCountingAllocator.numBlocksInUse());
533/// // assert(2 == defaultCountingAllocator.numBlocksTotal());
534/// assert(0 == objectCountingAllocator.numBlocksInUse());
535/// assert(1 == objectCountingAllocator.numBlocksTotal());
536/// assert(0 == defaultCountingAllocator.numBlocksInUse());
537/// assert(3 == defaultCountingAllocator.numBlocksTotal());
538/// @endcode
539/// Note that, although not necessary in the case of the simple `my_IdPair`
540/// class, the default allocator can be used (and typically *should* be used)
541/// within the body of a constructor, or any other member function, to allocate
542/// dynamic memory that is *temporarily* needed by the method (and, hence, not
543/// owned by the object after the method has returned). Thus, the invariant
544/// that must hold immediately after a method of an object returns is that the
545/// value returned by `defaultCountingAllocator.numBlocksInUse()` must be
546/// *identical* to what it was immediately prior to calling the method. Of
547/// course, note that the above invariant pertains to cases in *single*-threaded
548/// programs where the object allocator in use by the object is *distinct* from
549/// the default allocator. Also note that the value returned by
550/// `defaultCountingAllocator.numBlocksTotal()` *can* differ across function
551/// invocations (i.e., even in correct code).
552///
553/// ### Example 3: Basic Global Allocator Use {#bslma_default-example-3-basic-global-allocator-use}
554///
555///
556/// Next we define a simple singleton class, `my_Singleton`, that defaults to
557/// using the global allocator if one is not explicitly specified when the
558/// singleton object is initialized. Toward that end, note that in contrast to
559/// `my_Id`, the constructor for `my_Singleton` uses:
560/// @code
561/// bslma::Default::globalAllocator(basicAllocator)
562/// @endcode
563/// in its member initializer:
564/// @code
565/// // my_singleton.h
566///
567/// /// This is a trivial singleton class solely intended to illustrate use
568/// /// of the global allocator.
569/// class my_Singleton {
570///
571/// // CLASS DATA
572/// static my_Singleton *s_singleton_p; // pointer to singleton object
573///
574/// // PRIVATE DATA
575/// my_Id d_id; // allocating
576///
577/// private:
578/// // NOT IMPLEMENTED
579/// my_Singleton(const my_Singleton& original,
580/// bslma::Allocator *basicAllocator = 0);
581/// my_Singleton& operator=(const my_Singleton& rhs);
582///
583/// private:
584/// // PRIVATE CREATORS
585///
586/// /// Create a singleton having the specified `id`. Optionally
587/// /// specify a `basicAllocator` used to supply memory. If
588/// /// `basicAllocator` is 0, the currently installed global allocator
589/// /// is used.
590/// explicit my_Singleton(const char *id,
591/// bslma::Allocator *basicAllocator = 0);
592///
593/// /// Destroy this singleton.
594/// ~my_Singleton();
595///
596/// public:
597/// // CLASS METHODS
598///
599/// /// Initialize the singleton with the specified `id`. Optionally
600/// /// specify a `basicAllocator` used to supply memory. If
601/// /// `basicAllocator` is 0, the currently installed global allocator
602/// /// is used.
603/// static void initSingleton(const char *id,
604/// bslma::Allocator *basicAllocator = 0);
605///
606/// /// Return a reference to the non-modifiable singleton of this
607/// /// class. The behavior is undefined unless the singleton has been
608/// /// initialized.
609/// static const my_Singleton& singleton();
610///
611/// // ACCESSORS
612///
613/// /// Return the id of this singleton.
614/// const char *id() const;
615/// };
616///
617/// // CLASS METHODS
618/// inline
619/// const my_Singleton& my_Singleton::singleton()
620/// {
621/// return *s_singleton_p;
622/// }
623///
624/// // CREATORS
625/// inline
626/// my_Singleton::my_Singleton(const char *id,
627/// bslma::Allocator *basicAllocator)
628/// : d_id(id, bslma::Default::globalAllocator(basicAllocator))
629/// {
630/// }
631///
632/// inline
633/// my_Singleton::~my_Singleton()
634/// {
635/// }
636///
637/// // ACCESSORS
638/// inline
639/// const char *my_Singleton::id() const
640/// {
641/// return d_id.id();
642/// }
643/// @endcode
644/// The following completes the definition of `my_Singleton` in the component
645/// `.cpp` file:
646/// @code
647/// // my_singleton.cpp
648/// #include <my_singleton.h>
649/// #include <bsls_alignedbuffer.h>
650///
651/// my_Singleton *my_Singleton::s_singleton_p;
652///
653/// // CLASS METHODS
654/// void my_Singleton::initSingleton(const char *id,
655/// bslma::Allocator *basicAllocator)
656/// {
657/// static bsls::AlignedBuffer<sizeof(my_Singleton)> singleton;
658/// s_singleton_p = new (singleton.buffer()) my_Singleton(id,
659/// basicAllocator);
660/// }
661/// @endcode
662/// In the following, the default and global allocators are set to distinct
663/// instances of `my_CountingAllocator`. Note that the default allocator is set
664/// and locked identically to what was done in the previous two usage examples:
665/// @code
666/// static my_CountingAllocator defaultCountingAllocator;
667///
668/// int status = bslma::Default::setDefaultAllocator(
669/// &defaultCountingAllocator);
670/// assert(0 == status);
671/// bslma::Default::lockDefaultAllocator();
672/// assert(bslma::Default::defaultAllocator() == &defaultCountingAllocator);
673///
674/// static my_CountingAllocator globalCountingAllocator;
675///
676/// bslma::Default::setGlobalAllocator(&globalCountingAllocator);
677/// assert(bslma::Default::globalAllocator() == &globalCountingAllocator);
678/// @endcode
679/// Finally, we initialize the singleton object. We explicitly specify the
680/// desired allocator in the call to `initSingleton` to make our intentions as
681/// clear as possible. Of course, because of the way the `my_Singleton`
682/// constructor was written, the result would have been the same if no allocator
683/// had been specified. As in previous examples, the states of the default and
684/// global allocators are asserted before and after initializing the singleton:
685/// @code
686/// assert(0 == defaultCountingAllocator.numBlocksInUse());
687/// assert(0 == defaultCountingAllocator.numBlocksTotal());
688/// assert(0 == globalCountingAllocator.numBlocksInUse());
689/// assert(0 == globalCountingAllocator.numBlocksTotal());
690///
691/// my_Singleton::initSingleton("S", bslma::Default::globalAllocator());
692///
693/// assert(0 == defaultCountingAllocator.numBlocksInUse());
694/// assert(0 == defaultCountingAllocator.numBlocksTotal());
695/// assert(1 == globalCountingAllocator.numBlocksInUse());
696/// assert(1 == globalCountingAllocator.numBlocksTotal());
697/// @endcode
698/// @}
699/** @} */
700/** @} */
701
702/** @addtogroup bsl
703 * @{
704 */
705/** @addtogroup bslma
706 * @{
707 */
708/** @addtogroup bslma_default
709 * @{
710 */
711
712#include <bslscm_version.h>
713
715
716#include <bslma_allocator.h>
718
719
720
721namespace bslma {
722
723 // ==============
724 // struct Default
725 // ==============
726
727/// This struct is a mechanism with global state, i.e., all state is held in
728/// global variables and all functions are class methods. The state
729/// consists of two distinct parts that don't influence one another: the
730/// default allocator and the global allocator. All addresses are stored
731/// without assuming ownership.
732///
733/// The `setDefaultAllocator` method will only modify the default allocator
734/// prior to the default allocator being accessed (by either `allocator`,
735/// `defaultAllocator`, or `lockDefaultAllocator`). The global allocator may
736/// be freely modified.
737///
738///
739/// \note Note that *only* the *owner* of `main` (or in *testing*), where the
740/// caller affirmatively takes responsibility for the behavior of all
741/// clients of the global allocator, is intended to change the global
742/// allocator.
743///
744/// See @ref bslma_default
745struct Default {
746
747 private:
748 // CLASS DATA
749
750 // *** default allocator ***
751
752 /// The default allocator that is requested by the user and will be
753 /// installed as the default allocator on the first attempt to access
754 /// the default allocator (via `allocator`, `defaultAllocator`, or
755 /// `lockDefaultAllocator`). This value is initialized to `0`,
756 /// indicating the user hasn't made a choice yet. In that case, when
757 /// needed, the new-delete allocator will be used. This value can be
758 /// set (multiple times) by calling to `setDefaultAllocator`.
759 ///
760 /// \note Note that once changed this variable will not become `0` again.
761 static bsls::AtomicOperations::AtomicTypes::Pointer
762 s_requestedDefaultAllocator;
763
764 /// The currently installed default allocator. This variable must be
765 /// set only once, when the default allocator is first accessed (via
766 /// `allocator`, `defaultAllocator`, or `lockDefaultAllocator`) but may
767 /// be `0` before it is accessed unless *for* *testing* *only*
768 /// `setDefaultAllocatorRaw` is used.
769 static bsls::AtomicOperations::AtomicTypes::Pointer s_defaultAllocator;
770
771 // *** global allocator ***
772
773 /// The address of the global allocator to use.
774 static bsls::AtomicOperations::AtomicTypes::Pointer s_globalAllocator;
775
776 // PRIVATE CLASS METHODS
777
778 /// Return the address of the default allocator and disable all
779 /// subsequent calls to the `setDefaultAllocator` method. If
780 /// `s_defaultAllocator` is 0 (meaning the default allocator has not yet
781 /// been accessed), set it to the last value supplied to
782 /// `setDefaultAllocator` (stored in `s_requestedDefaultAllocator`). If
783 /// `s_requestedDefaultAllocator` is 0 (meaning `setDefaultAllocator`
784 /// has not been called) set `s_defaultAllocator` and
785 /// `s_requestedDefaultAllocator` to be the new-delete allocator.
786 ///
787 /// \note Note that this operation performs the one and only assigment to
788 /// `s_defaultAllocator` (unless `setDefaultAllocatorRaw` is called).
789 /// In C++, this function also ensures that the default
790 /// `std::pmr::memory_resource` is the same as the default `Allocator`.
791 /// Note also that this function has the same externally visible
792 /// behavior as `defaultAllocator`, but forms the (thread-safe)
793 /// "slow-path" for that function's implementation.
794 static Allocator *determineAndReturnDefaultAllocator();
795
796 public:
797 // CLASS METHODS
798
799 // *** default allocator ***
800
801 /// Set the address of the default allocator to the specified
802 /// `basicAllocator` unless calls to this method have been disabled.
803 /// Return 0 on success and a non-zero value otherwise. This method
804 /// will fail if either `defaultAllocator`, `lockDefaultAllocator`, or
805 /// `allocator` with argument 0 has been called previously in this
806 /// process. In C++17 and later, a successful call to this method will
807 /// also set the default `std::pmr::memory_resource`.
808 ///
809 /// \pre The behavior is undefined unless `basicAllocator` is the address of an allocator
810 /// with sufficient lifetime to satisfy all allocation requests within
811 /// this process, and unless there is only one thread started within this process.
812 ///
813 /// \note Note that this method is intended for use *only* by
814 /// the *owner* of `main` (or for use in *testing*) where the caller
815 /// affirmatively takes responsibility for the behavior of all clients
816 /// of the default allocator, and should *not* be used for any other
817 /// purpose.
818 static int setDefaultAllocator(Allocator *basicAllocator);
819
820 /// Unconditionally set the address of the default allocator to the
821 /// specified `basicAllocator`. In C++17 and later, a call to this
822 /// method will also set the default `std::pmr::memory_resource`.
823 ///
824 /// \pre The behavior is undefined unless `basicAllocator` is the address of an
825 /// allocator with sufficient lifetime to satisfy all allocation
826 /// requests within this process, and unless there is only one thread started within this process.
827 ///
828 /// \note Note that this method is intended for
829 /// use *only* in *testing* where the caller affirmatively takes
830 /// responsibility for the behavior of all clients of the default
831 /// allocator, and should *not* be used for any other purpose.
832 static void setDefaultAllocatorRaw(Allocator *basicAllocator);
833
834 /// Disable all subsequent calls to the `setDefaultAllocator` method.
835 /// Subsequent calls to this method have no effect.
836 ///
837 /// \note Note that subsequent calls to the `setDefaultAllocatorRaw` method are *not*
838 /// disabled by this method.
839 static void lockDefaultAllocator();
840
841 /// Return the address of the default allocator and disable all
842 /// subsequent calls to the `setDefaultAllocator` method.
843 ///
844 /// \note Note that prior to the first call to `setDefaultAllocator` or
845 /// `setDefaultAllocatorRaw` methods, the address of the default
846 /// allocator is that of the `NewDeleteAllocator` singleton. Also note
847 /// that subsequent calls to `setDefaultAllocatorRaw` method are *not*
848 /// disabled by this method.
849 static Allocator *defaultAllocator();
850
851 /// Return the allocator returned by `defaultAllocator` and disable all
852 /// subsequent calls to the `setDefaultAllocator` method if the
853 /// optionally-specified `basicAllocator` is 0; return `basicAllocator`
854 /// otherwise.
855 static Allocator *allocator(Allocator *basicAllocator = 0);
856
857 // *** global allocator ***
858
859 /// Return the address of the global allocator if the optionally-
860 /// specified `basicAllocator` is 0, and `basicAllocator` otherwise.
861 ///
862 /// \note Note that prior to the first call to the `setGlobalAllocator`
863 /// method, the address of the global allocator is that of the
864 /// `NewDeleteAllocator` singleton.
865 static Allocator *globalAllocator(Allocator *basicAllocator = 0);
866
867 /// Unconditionally set the address of the global allocator to the
868 /// specified `basicAllocator`, or to the address of the
869 /// `NewDeleteAllocator` singleton if `basicAllocator` is 0. Return the
870 /// address of the global allocator in effect immediately before calling this method.
871 ///
872 /// \pre The behavior is undefined unless `basicAllocator` is 0
873 /// or is the address of an allocator with sufficient lifetime to
874 /// satisfy all global allocation requests within this process, and
875 /// unless there is only one thread started within this process.
876 ///
877 /// \note Note that prior to the first call to this method, the address of the
878 /// global allocator is that of the `NewDeleteAllocator` singleton.
879 /// Also note that this method is intended for use *only* by the *owner*
880 /// of `main` (or for use in *testing*) where the caller affirmatively
881 /// takes responsibility for the behavior of all clients of the global
882 /// allocator, and should *not* be used for any other purpose.
883 static Allocator *setGlobalAllocator(Allocator *basicAllocator);
884};
885
886// ============================================================================
887// INLINE FUNCTION DEFINITIONS
888// ============================================================================
889
890 // --------------
891 // struct Default
892 // --------------
893
894// CLASS METHODS
895
896 // *** default allocator ***
897
898inline
900{
901 determineAndReturnDefaultAllocator();
902}
903
904inline
906{
907 void *alloc = bsls::AtomicOperations::getPtrRelaxed(&s_defaultAllocator);
908 return alloc ? static_cast<Allocator *>(alloc)
909 : determineAndReturnDefaultAllocator();
910}
911
912inline
914{
915 return basicAllocator ? basicAllocator : defaultAllocator();
916}
917
918 // *** global allocator ***
919
920inline
922{
923 Allocator *globalAllocator = static_cast<Allocator *>(const_cast<void *>(
924 bsls::AtomicOperations::getPtrAcquire(&s_globalAllocator)));
925
926 return basicAllocator ? basicAllocator
930}
931
932#ifdef BSLS_LIBRARYFEATURES_HAS_CPP17_PMR
933
934/// Stateless class to set the initial default resource to
935/// `bslma::NewDeleteAllocator` automatically when using this component
936/// with a platform that supports C++17 `std::pmr::memory_resource`.
937///
938/// See @ref bslma_default
939struct Default_NewDeleteSetter {
940
941 /// If `std::pmr::set_default_resource` has not yet been invoked, call
942 /// it with the address of the `bslma::NewDeleteAllocator` singleton,
943 /// thus ensuring that `bslma::Default` and @ref get_default_resource are
944 /// in sync.
945 Default_NewDeleteSetter();
946
947 Default_NewDeleteSetter(const Default_NewDeleteSetter&) = delete;
948};
949
950/// Static initialization of this variable ensures that the default resource
951/// is set to `NewDeleteAllocator` before it is read by other code.
952static Default_NewDeleteSetter Default_NewDeleteSetterSingleton;
953
954#endif // BSLS_LIBRARYFEATURES_HAS_CPP17_PMR
955
956} // close package namespace
957
958#ifndef BDE_OPENSOURCE_PUBLICATION // BACKWARD_COMPATIBILITY
959
960// ============================================================================
961// BACKWARD COMPATIBILITY
962// ============================================================================
963
964#ifndef BDE_OMIT_INTERNAL_DEPRECATED
965 // ====================
966 // struct bdema_Default
967 // ====================
968
969/// This `struct` is a namespace for functions that manipulate and access
970/// the default and global allocator pointers. This alias is defined for
971/// backward compatibility.
973
974#endif // BDE_OMIT_INTERNAL_DEPRECATED
975
976/// This alias is defined for backward compatibility.
978
979#endif // BDE_OPENSOURCE_PUBLICATION -- BACKWARD_COMPATIBILITY
980
981
982
983#endif
984
985// ----------------------------------------------------------------------------
986// Copyright 2013 Bloomberg Finance L.P.
987//
988// Licensed under the Apache License, Version 2.0 (the "License");
989// you may not use this file except in compliance with the License.
990// You may obtain a copy of the License at
991//
992// http://www.apache.org/licenses/LICENSE-2.0
993//
994// Unless required by applicable law or agreed to in writing, software
995// distributed under the License is distributed on an "AS IS" BASIS,
996// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
997// See the License for the specific language governing permissions and
998// limitations under the License.
999// ----------------------------- END-OF-FILE ----------------------------------
1000
1001/** @} */
1002/** @} */
1003/** @} */
Definition bslma_allocator.h:545
static NewDeleteAllocator & singleton()
bslma::Default bslma_Default
This alias is defined for backward compatibility.
Definition bslma_default.h:977
bslma::Default bdema_Default
Definition bslma_default.h:972
#define BSLS_IDENT(str)
BSLS_IDENT() - insert string into .comment binary segment (if supported)
Definition bsls_ident.h:238
Definition baljsn_encoder_testtypes.h:76
Definition bslma_default.h:745
static Allocator * globalAllocator(Allocator *basicAllocator=0)
Definition bslma_default.h:921
static Allocator * setGlobalAllocator(Allocator *basicAllocator)
static Allocator * allocator(Allocator *basicAllocator=0)
Definition bslma_default.h:913
static void setDefaultAllocatorRaw(Allocator *basicAllocator)
static void lockDefaultAllocator()
Definition bslma_default.h:899
static int setDefaultAllocator(Allocator *basicAllocator)
static Allocator * defaultAllocator()
Definition bslma_default.h:905
static void * getPtrAcquire(AtomicTypes::Pointer const *atomicPtr)
Definition bsls_atomicoperations.h:2314
static void * getPtrRelaxed(AtomicTypes::Pointer const *atomicPtr)
Definition bsls_atomicoperations.h:2320