BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bslma_newdeleteallocator.h
Go to the documentation of this file.
1/// @file bslma_newdeleteallocator.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bslma_newdeleteallocator.h -*-C++-*-
8#ifndef INCLUDED_BSLMA_NEWDELETEALLOCATOR
9#define INCLUDED_BSLMA_NEWDELETEALLOCATOR
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bslma_newdeleteallocator bslma_newdeleteallocator
15/// @brief Provide singleton new/delete adaptor to `bslma::Allocator` protocol.
16/// @addtogroup bsl
17/// @{
18/// @addtogroup bslma
19/// @{
20/// @addtogroup bslma_newdeleteallocator
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bslma_newdeleteallocator-purpose"> Purpose</a>
25/// * <a href="#bslma_newdeleteallocator-classes"> Classes </a>
26/// * <a href="#bslma_newdeleteallocator-description"> Description </a>
27/// * <a href="#bslma_newdeleteallocator-thread-safety"> Thread Safety </a>
28/// * <a href="#bslma_newdeleteallocator-usage"> Usage </a>
29///
30/// # Purpose {#bslma_newdeleteallocator-purpose}
31/// Provide singleton new/delete adaptor to `bslma::Allocator` protocol.
32///
33/// # Classes {#bslma_newdeleteallocator-classes}
34///
35/// - bslma::NewDeleteAllocator: support new/delete-style allocation/deallocation
36///
37/// @see bslma_default, bslma_testallocator
38///
39/// # Description {#bslma_newdeleteallocator-description}
40/// This component provides a concrete allocation mechanism,
41/// `bslma::NewDeleteAllocator`, that implements the `bslma::Allocator` protocol
42/// to provide direct access to the system-supplied (native) global
43/// `operator new` and `operator delete` functions via that pure abstract
44/// interface.
45/// @code
46/// ,-------------------------.
47/// ( bslma::NewDeleteAllocator )
48/// `-------------------------'
49/// | allocator
50/// | singleton
51/// | ctor/dtor
52/// V
53/// ,----------------.
54/// ( bslma::Allocator )
55/// `----------------'
56/// allocate
57/// deallocate
58/// @endcode
59/// The essential purpose of this component is to facilitate the default use of
60/// global `new` and `delete` in all components that accept a user-supplied
61/// allocator derived from `bslma::Allocator` (see @ref bslma_default ). Hence, the
62/// global `operator new` and `operator delete` functions are wrapped within
63/// concrete methods of a derived `bslma::NewDeleteAllocator` class. A `static`
64/// (factory) method of `bslma::NewDeleteAllocator` can be used to obtain a
65/// unique (singleton) `bslma::NewDeleteAllocator` object for the given process,
66/// and whose lifetime is guaranteed to exceed any possibility of its use. Note
67/// that the standard also requires the global `operator new` to return
68/// maximally-aligned memory, which is a stricter post condition than the
69/// natural-alignment requirement imposed by the base-class contract, or than is
70/// provided by many other concrete implementations.
71///
72/// ## Thread Safety {#bslma_newdeleteallocator-thread-safety}
73///
74///
75/// This class is fully thread-safe, which means that all non-creator object
76/// methods can be safely accessed concurrently (from multiple treads). The
77/// singleton `bslma::NewDeleteAllocator` can also be safely created/accessed
78/// concurrently (from multiple threads) via either the `static` `singleton` or
79/// `allocator` (factory) methods. Moreover, the underlying (native)
80/// implementation of `new` and `delete` are required by the C++ standard to
81/// ensure that concurrent access to either the virtual `allocate` and/or
82/// `deallocate` are also safe (i.e., will not not result in heap corruption).
83/// Note that this allocator therefore has stronger thread-safety guarantees
84/// than is required by the base-class contract or than is provided by many
85/// other derived concrete allocators.
86///
87/// ## Usage {#bslma_newdeleteallocator-usage}
88///
89///
90/// The most common and proper use of `bslma::NewDeleteAllocator` is both
91/// *indirect* and *by* *default* (see @ref bslma_default ). For example, consider
92/// (along with its destructor) the default and copy constructors for, say, a
93/// simple container, such as `my_ShortArray`, each of which take as its final
94/// optional argument the address of a `bslma::Allocator` protocol:
95/// @code
96/// // my_shortarray.h:
97/// // ...
98/// namespace bslma { class Allocator; }
99///
100/// class my_ShortArray {
101/// short *d_array_p; // dynamically-allocated array
102/// int d_capacity; // physical capacity (in elements)
103/// int d_length; // logical length (in elements)
104/// bslma::Allocator *d_allocator_p; // memory allocator (not owned)
105///
106/// public:
107/// /// Create an empty `my_shortArray`. Optionally specify a
108/// /// `basicAllocator` used to supply memory. If `basicAllocator`
109/// /// is 0, the currently installed default allocator is used.
110/// my_ShortArray(bslma::Allocator *basicAllocator = 0);
111///
112/// /// Create a `bslma::ShortArray` having the same value as the
113/// /// specified `other` array. Optionally specify a `basicAllocator`
114/// /// used to supply memory. If `basicAllocator` is 0, the currently
115/// /// installed default allocator is used.
116/// my_ShortArray(const my_ShortArray& other,
117/// bslma::Allocator *basicAllocator = 0);
118///
119/// /// Destroy this object.
120/// ~my_ShortArray();
121///
122/// // ...
123/// };
124///
125/// // ...
126/// @endcode
127/// In order to satisfy this contract, we will need a globally accessible
128/// utility (see @ref bslma_default ), which by default returns the singleton
129/// `bslma::NewDeleteAllocator`, but which could be configured to return some
130/// other allocator, say a *test* allocator (see @ref bslma_testallocator ):
131/// @code
132/// // my_default.h:
133/// // ...
134/// namespace bslma { class Allocator; }
135///
136/// /// This class maintains a process-wide `bslma::Allocator` object
137/// /// to be used when an allocator is needed, and not suppled explicitly.
138/// /// By default, the currently installed default allocator is the unique
139/// /// `bslma::NewDeleteAllocator` object returned by the `static` method,
140/// /// `bslma::NewDeleteAllocator::singleton()`. Note that the default
141/// /// allocator will exist longer than any possibility of its use.
142/// struct my_Default {
143///
144/// /// Return the address of the specified modifiable
145/// /// `basicAllocator` or, if `basicAllocator` is 0, an instance of
146/// /// the currently installed default `bslma::Allocator` object, which
147/// /// will exist longer than any possibility of its use. Note
148/// /// that this function can safely be called concurrently (from
149/// /// multiple threads).
150/// static bslma::Allocator *allocator(bslma::Allocator *basicAllocator);
151///
152/// /// Replace the address of the currently installed allocator with
153/// /// that of the specified modifiable `basicAllocator` (or if 0,
154/// /// with the "factory" default, `bslma::NewDeleteAllocator`), and
155/// /// return the address of the previous allocator. The behavior is
156/// /// undefined unless `basicAllocator` will exist longer than any
157/// /// possibility of its use. Note that this function is *not* *at*
158/// /// *all* thread-safe, and should *never* be called when multiple
159/// /// threads are active.
160/// static bslma::Allocator *replace(bslma::Allocator *basicAllocator);
161/// };
162///
163/// // my_default.cpp:
164/// // ...
165///
166/// #include <my_default.h>
167///
168/// static bslma::Allocator *s_default_p = 0; // load-time initialized
169///
170/// bslma::Allocator *my_Default::allocator(bslma::Allocator *basicAllocator)
171/// {
172/// return bslma::NewDeleteAllocator::allocator(s_default_p);
173/// }
174///
175/// bslma::Allocator *my_Default::replace(bslma::Allocator *basicAllocator)
176/// {
177/// bslma::Allocator *tmp =
178/// bslma::NewDeleteAllocator::allocator(s_default_p);
179/// s_default_p = bslma::NewDeleteAllocator::allocator(basicAllocator);
180/// return tmp;
181/// }
182/// @endcode
183/// Notice that the only part of the `bslma::NewDeleteAllocator` class we used
184/// directly was its static `allocator` method, which -- in addition to safely
185/// constructing the singleton `bslma::NewDeleteAllocator` object on first
186/// access -- also automatically replaces a 0 address value with that of
187/// singleton `bslma::NewDeleteAllocator` object. From now on, we will never
188/// again need to invoke the @ref bslma_newdeleteallocator component's interface
189/// directly, but instead use it through `my_Default` (see `bslma::Default` for
190/// what is actually used in practice).
191///
192/// Turning back to our `my_shortarray` example, let's now implement the two
193/// constructors using the @ref bslma_newdeleteallocator component indirectly via
194/// the `my_default` component:
195/// @code
196/// // my_shortarray.cpp:
197/// #include <my_shortarray.h>
198/// #include <my_default.h>
199/// #include <bsls_assert.h>
200///
201/// // ...
202///
203/// enum {
204/// INITIAL_CAPACITY = 0, // recommended to avoid unnecessary allocations
205/// // possibly resulting in locking and extra thread
206/// // contention for the 'bslma::NewDeleteAllocator'
207///
208/// GROW_FACTOR = 2 // typical value for geometric growth
209/// };
210///
211/// // ...
212///
213/// my_ShortArray::my_ShortArray(bslma::Allocator *basicAllocator)
214/// : d_capacity(INITIAL_CAPACITY)
215/// , d_length(0)
216/// , d_allocator_p(my_Default::allocator(basicAllocator))
217/// {
218/// assert(d_allocator_p);
219/// d_array_p = (short *) // no thread contention if 'd_capacity' is 0
220/// d_allocator_p->allocate(d_capacity * sizeof *d_array_p);
221/// assert(0 == d_array_p);
222/// }
223///
224/// my_ShortArray::my_ShortArray(const my_ShortArray& other,
225/// bslma::Allocator *basicAllocator)
226/// : d_capacity(other.d_capacity)
227/// , d_length(other.d_length)
228/// , d_allocator_p(my_Default::allocator(basicAllocator))
229/// {
230/// assert(d_allocator_p);
231/// d_array_p = (short *)
232/// d_allocator_p->allocate(d_capacity * sizeof *d_array_p);
233/// assert(!d_capacity == !d_array_p);
234/// memcpy(d_array_p, other.d_array_p, d_length * sizeof *d_array_p);
235/// }
236///
237/// my_ShortArray::~my_ShortArray()
238/// {
239/// d_allocator_p->deallocate(d_array_p); // no locking if 'd_array_p' is 0
240/// }
241///
242/// // ...
243/// @endcode
244/// When the default constructor is called, the default capacity and length are
245/// recorded in data members via the initialization list. The static function
246/// `allocator` (provided in `my_Default`) is used to assign the value of the
247/// `basicAllocator` address passed in, or if that is 0, the address of the
248/// currently installed default allocator, which by default is the singleton
249/// object of type `bslma::NewDeleteAllocator`, defined in this component. Note
250/// that since `INITIAL_CAPACITY` is 0, a default constructed object that is
251/// created using a `bslma::NewDeleteAllocator` will *not* invoke the
252/// `operator new` function, which on some platforms may needlessly acquire a
253/// lock, causing unnecessary overhead (the same potential overhead is avoided
254/// for `operator delete` whenever a 0 `d_array_p` value is deallocated in the
255/// destructor) and `d_allocator_p` refers to a `bslma::NewDeleteAllocator`.
256/// Note also that, for the copy constructor, the currently installed default
257/// allocator, and not the `other` array's allocator is used whenever
258/// `basicAllocator` is 0 or not explicitly supplied.
259///
260/// Finally note that this entire component is *not* intended for direct use by
261/// typical clients: See @ref bslma_default for more information or proper usage.
262/// @}
263/** @} */
264/** @} */
265
266/** @addtogroup bsl
267 * @{
268 */
269/** @addtogroup bslma
270 * @{
271 */
272/** @addtogroup bslma_newdeleteallocator
273 * @{
274 */
275
276#include <bslscm_version.h>
277
278#include <bslma_allocator.h>
279
280#include <bsls_keyword.h>
281
282
283
284namespace bslma {
285
286 // ========================
287 // class NewDeleteAllocator
288 // ========================
289
290/// This class defines a concrete mechanism that adapts the system-supplied
291/// (native) global `operator new` and `operator delete` to the `Allocator`
292/// protocol. The class method `singleton` returns a process-wide unique
293/// object of this class whose lifetime is guaranteed to extend from the
294/// first call to `singleton` until the program terminates. A second class
295/// method, `allocator`, allows for conveniently replacing a "null"
296/// allocator with this singleton object. Note that this entire class
297/// should generally not be used directly by typical clients (see
298/// @ref bslma_default for more information).
299///
300/// See @ref bslma_newdeleteallocator
302
303 private:
304 // NOT IMPLEMENTED
306 NewDeleteAllocator& operator=(const NewDeleteAllocator&);
307
308 public:
309 // CLASS METHODS
310
311 /// Return a reference to a process-wide unique object of this class.
312 /// The lifetime of this object is guaranteed to extend from the first
313 /// call of this method until the program terminates. Note that this
314 /// method should generally not be used directly by typical clients (see
315 /// @ref bslma_default for more information).
317
318 /// Return the address of the specified modifiable `basicAllocator` or,
319 /// if `basicAllocator` is 0, the process-wide unique (see `singleton`)
320 /// object of this class. Note that the behavior of this function is
321 /// equivalent to the following expression:
322 /// @code
323 /// basicAllocator
324 /// ? basicAllocator
325 /// : &NewDeleteAllocator::singleton()
326 /// @endcode
327 /// Also note that if a `NewDeleteAllocator` object is supplied, it is
328 /// owned by the class and must NOT be deleted. Finally note that this
329 /// method should generally not be called directly by typical clients
330 /// (see @ref bslma_default for more information).
331 static Allocator *allocator(Allocator *basicAllocator);
332
333 // CREATORS
334
335 /// Create a ("stateless") new-delete-allocator object that wraps the
336 /// global native `operator new` and `operator delete` functions in
337 /// order to supply memory via the `Allocator` protocol. Note that all
338 /// objects of this class share the same underlying resource; hence,
339 /// this constructor should generally not be invoked directly by
340 /// clients; instead, consider using the `static` `singleton` or
341 /// `allocator` (factory) methods, or -- better -- the appropriate ones
342 /// in `Default` (see @ref bslma_default for more information).
344
345 /// Destroy this allocator object. Note that destroying this allocator
346 /// has no effect on any outstanding allocated memory.
348
349 // MANIPULATORS
350
351 /// Return a newly allocated block of memory of (at least) the specified
352 /// positive `size` (in bytes). If `size` is 0, a null pointer is
353 /// returned with no other effect. The alignment of the address
354 /// returned is the maximum alignment for any fundamental, pointer, or
355 /// enumerated type defined for this platform. The behavior is
356 /// undefined unless `0 <= size`. Note that global `operator new` is
357 /// *not* called when `size` is 0 (in order to avoid having to acquire a
358 /// lock, and potential contention in multi-threaded programs).
360
361 /// Return the memory block at the specified `address` back to this
362 /// allocator. If `address` is 0, this function has no effect. The
363 /// behavior is undefined unless `address` was allocated using this
364 /// allocator object and has not already been deallocated. Note that
365 /// global `operator delete` is *not* called when `address` is 0 (in
366 /// order to avoid having to acquire a lock, and potential contention in
367 /// multi-threaded programs).
368 void deallocate(void *address) BSLS_KEYWORD_OVERRIDE;
369};
370
371// ============================================================================
372// INLINE DEFINITIONS
373// ============================================================================
374
375 // ------------------------
376 // class NewDeleteAllocator
377 // ------------------------
378
379// CLASS METHODS
380inline
382{
383 return basicAllocator ? basicAllocator : &singleton();
384}
385
386// CREATORS
387inline
391
392// MANIPULATORS
393inline
395{
396 // While the C++ standard guarantees that calling delete(0) is safe
397 // (3.7.3.2 paragraph 3), some libc implementations take out a lock to deal
398 // with the free(0) case, so this check can improve efficiency of threaded
399 // programs.
400
401 if (address) {
402 ::operator delete(address);
403 }
404}
405
406} // close package namespace
407
408#ifndef BDE_OPENSOURCE_PUBLICATION // BACKWARD_COMPATIBILITY
409// ============================================================================
410// BACKWARD COMPATIBILITY
411// ============================================================================
412
413/// This alias is defined for backward compatibility.
415#endif // BDE_OPENSOURCE_PUBLICATION -- BACKWARD_COMPATIBILITY
416
417
418
419#endif
420
421// ----------------------------------------------------------------------------
422// Copyright 2013 Bloomberg Finance L.P.
423//
424// Licensed under the Apache License, Version 2.0 (the "License");
425// you may not use this file except in compliance with the License.
426// You may obtain a copy of the License at
427//
428// http://www.apache.org/licenses/LICENSE-2.0
429//
430// Unless required by applicable law or agreed to in writing, software
431// distributed under the License is distributed on an "AS IS" BASIS,
432// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
433// See the License for the specific language governing permissions and
434// limitations under the License.
435// ----------------------------- END-OF-FILE ----------------------------------
436
437/** @} */
438/** @} */
439/** @} */
Definition bslma_allocator.h:457
std::size_t size_type
Definition bslma_allocator.h:499
Definition bslma_newdeleteallocator.h:301
static Allocator * allocator(Allocator *basicAllocator)
Definition bslma_newdeleteallocator.h:381
~NewDeleteAllocator() BSLS_KEYWORD_OVERRIDE
void * allocate(size_type size) BSLS_KEYWORD_OVERRIDE
void deallocate(void *address) BSLS_KEYWORD_OVERRIDE
Definition bslma_newdeleteallocator.h:394
NewDeleteAllocator()
Definition bslma_newdeleteallocator.h:388
static NewDeleteAllocator & singleton()
bslma::NewDeleteAllocator bslma_NewDeleteAllocator
This alias is defined for backward compatibility.
Definition bslma_newdeleteallocator.h:414
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
#define BSLS_KEYWORD_OVERRIDE
Definition bsls_keyword.h:653
Definition balxml_encoderoptions.h:68