BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bslstl_allocator.h
Go to the documentation of this file.
1/// @file bslstl_allocator.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bslstl_allocator.h -*-C++-*-
8#ifndef INCLUDED_BSLSTL_ALLOCATOR
9#define INCLUDED_BSLSTL_ALLOCATOR
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bslstl_allocator bslstl_allocator
15/// @brief Provide an STL-compatible proxy for `bslma::Allocator` objects.
16/// @addtogroup bsl
17/// @{
18/// @addtogroup bslstl
19/// @{
20/// @addtogroup bslstl_allocator
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bslstl_allocator-purpose"> Purpose</a>
25/// * <a href="#bslstl_allocator-classes"> Classes </a>
26/// * <a href="#bslstl_allocator-description"> Description </a>
27/// * <a href="#bslstl_allocator-restrictions-on-allocator-usage"> Restrictions on Allocator Usage </a>
28/// * <a href="#bslstl_allocator-usage"> Usage </a>
29///
30/// # Purpose {#bslstl_allocator-purpose}
31/// Provide an STL-compatible proxy for `bslma::Allocator` objects.
32///
33/// @deprecated Use @ref bslma_bslallocator instead.
34///
35/// # Classes {#bslstl_allocator-classes}
36///
37/// - bsl::allocator: STL-compatible allocator template
38/// - bsl::allocator_traits<bsl::allocator>: specialization for `bsl::allocator`
39///
40/// **Canonical header:** bsl_memory.h
41///
42/// @see bslma_bslallocator
43///
44/// # Description {#bslstl_allocator-description}
45/// This component is for internal use only. Please include
46/// `<bsl_memory.h>` instead and use `bsl::allocator` directly. This component
47/// provides an STL-compatible proxy for any allocator class derived from
48/// `bslma::Allocator`. The proxy class, `bsl::allocator` is a template that
49/// adheres to the allocator requirements defined in section 20.1.5
50/// [lib.allocator.requirements] of the C++ standard. `bsl::allocator` may be
51/// used to instantiate any class template that is parameterized by a standard
52/// allocator. The container is expected to allocate memory for its own use
53/// through the allocator. Different types of allocator use different
54/// allocation mechanisms, so this mechanism gives the programmer control over
55/// how the container obtains memory.
56///
57/// The `bsl::allocator` template is intended to solve a problem created by the
58/// C++ standard allocator protocol. Since, in STL, the allocator type is
59/// specified as a container template parameter, the allocation mechanism
60/// becomes an explicit part of the resulting container type. Two containers
61/// cannot be of the same type unless they are instantiated with the same
62/// allocator type, and therefore the same allocation mechanism.
63/// `bsl::allocator` breaks the connection between allocator type and allocation
64/// mechanism. The allocation mechanism is chosen at *run-time* by
65/// *initializing* (contrast with *instantiating*) the `bsl::allocator` with a
66/// pointer to a *mechanism* *object* derived from `bslma::Allocator`. Each
67/// class derived from `bslma::Allocator` implements a specific allocation
68/// mechanism and is thus called a *mechanism* *class* within this component.
69/// The `bsl::allocator` object forwards calls made through the standard
70/// allocator interface to the mechanism object with which it was initialized.
71/// In this way, two containers instantiated with `bsl::allocator` can utilize
72/// different allocation mechanisms even though they have the same compile-time
73/// type. The default mechanism object, if none is supplied to the
74/// `bsl::allocator` constructor, is `bslma::Default::defaultAllocator()`.
75///
76/// Instantiations of `bsl::allocator` have full value semantics (well-behaved
77/// copy construction, assignment, and tests for equality). Note, however, that
78/// a `bsl::allocator` object does not "own" the `bslma::Allocator` with which
79/// it is initialized. In practice , this means that copying a `bsl::allocator`
80/// object does not copy its mechanism object and destroying a `bsl::allocator`
81/// does not destroy its mechanism object. Two `bsl::allocator` objects compare
82/// equal if and only if they share the same mechanism object.
83///
84/// ## Restrictions on Allocator Usage {#bslstl_allocator-restrictions-on-allocator-usage}
85///
86///
87/// The allocator requirements section of the C++ standard (section 20.1.5
88/// [lib.allocator.requirements]) permits containers to assume that two
89/// allocators of the same type always compare equal. This assumption is
90/// incorrect for instantiations of `bsl::allocator`. Therefore, any container
91/// (or other facility) that can use `bsl::allocator` must operate correctly in
92/// the presence of non-equal `bsl::allocator` objects. In practice, this means
93/// that a container cannot transfer ownership of allocated memory to another
94/// container unless the two containers use equal allocators. Two
95/// `bsl::allocator` objects will compare equal if and only if they were
96/// initialized with the same mechanism object.
97///
98/// ## Usage {#bslstl_allocator-usage}
99///
100///
101/// We first show how to define a container type parameterized with an STL-style
102/// allocator template parameter. For simplicity, we choose a fixed-size array
103/// to avoid issues concerning reallocation, dynamic growth, etc. Furthermore,
104/// we do not assume the `bslma` allocation protocol, which would dictate that
105/// we pass-through the allocator to the parameterized `T` contained type (see
106/// the @ref bslma_allocator component and `bslalg` package). The interface would
107/// be as follows:
108/// @code
109/// // my_fixedsizearray.h
110/// // ...
111///
112/// // =======================
113/// // class my_FixedSizeArray
114/// // =======================
115///
116/// /// This class provides an array of the parameterized `T` type passed of
117/// /// fixed length at construction, using an object of the parameterized
118/// /// `ALLOC` type to supply memory.
119/// template <class T, class ALLOC>
120/// class my_FixedSizeArray {
121///
122/// // DATA
123/// ALLOC d_allocator;
124/// int d_length;
125/// T *d_array;
126///
127/// public:
128/// // TYPES
129/// typedef ALLOC allocator_type;
130/// typedef T value_type;
131///
132/// // CREATORS
133///
134/// /// Create a fixed-size array of the specified `length`, using the
135/// /// optionally specified `allocator` to supply memory. If
136/// /// `allocator` is not specified, a default-constructed object of
137/// /// the parameterized `ALLOC` type is used. Note that all the
138/// /// elements in that array are default-constructed.
139/// my_FixedSizeArray(int length, const ALLOC& allocator = ALLOC());
140///
141/// /// Create a copy of the specified `original` fixed-size array,
142/// /// using the optionally specified `allocator` to supply memory. If
143/// /// `allocator` is not specified, a default-constructed object of
144/// /// the parameterized `ALLOC` type is used.
145/// my_FixedSizeArray(const my_FixedSizeArray& original,
146/// const ALLOC& allocator = ALLOC());
147///
148/// /// Destroy this fixed size array.
149/// ~my_FixedSizeArray();
150///
151/// // MANIPULATORS
152///
153/// /// Return a reference to the modifiable element at the specified
154/// /// `index` position in this fixed size array.
155/// T& operator[](int index);
156///
157/// // ACCESSORS
158///
159/// /// Return a reference to the modifiable element at the specified
160/// /// `index` position in this fixed size array.
161/// const T& operator[](int index) const;
162///
163/// /// Return the length specified at construction of this fixed size
164/// // array.
165/// int length() const;
166///
167/// /// Return a reference to the non-modifiable allocator used by this
168/// /// fixed size array to supply memory. This is here for
169/// /// illustrative purposes. We should not generally have an accessor
170/// /// to return the allocator.
171/// const ALLOC& allocator() const;
172/// };
173///
174/// // FREE OPERATORS
175///
176/// /// Return `true` if the specified `lhs` fixed-size array has the same
177/// /// value as the specified `rhs` fixed-size array, and `false`
178/// /// otherwise. Two fixed-size arrays have the same value if they have
179/// /// the same length and if the element at any index in `lhs` has the
180/// /// same value as the corresponding element at the same index in `rhs`.
181/// template<class T, class ALLOC>
182/// bool operator==(const my_FixedSizeArray<T,ALLOC>& lhs,
183/// const my_FixedSizeArray<T,ALLOC>& rhs)
184/// @endcode
185/// The implementation is straightforward
186/// @code
187/// // my_fixedsizearray.cpp
188/// // ...
189/// // -----------------------
190/// // class my_FixedSizeArray
191/// // -----------------------
192///
193/// // CREATORS
194/// template<class T, class ALLOC>
195/// my_FixedSizeArray<T,ALLOC>::my_FixedSizeArray(int length,
196/// const ALLOC& allocator)
197/// : d_allocator(allocator), d_length(length)
198/// {
199/// d_array = d_allocator.allocate(d_length); // sizeof(T)*d_length bytes
200///
201/// // Default construct each element of the array:
202/// for (int i = 0; i < d_length; ++i) {
203/// d_allocator.construct(&d_array[i], T());
204/// }
205/// }
206///
207/// template<class T, class ALLOC>
208/// my_FixedSizeArray<T,ALLOC>::my_FixedSizeArray(
209/// const my_FixedSizeArray& original,
210/// const ALLOC& allocator)
211/// : d_allocator(allocator), d_length(original.d_length)
212/// {
213/// d_array = d_allocator.allocate(d_length); // sizeof(T)*d_length bytes
214///
215/// // copy construct each element of the array:
216/// for (int i = 0; i < d_length; ++i) {
217/// d_allocator.construct(&d_array[i], original.d_array[i]);
218/// }
219/// }
220///
221/// template<class T, class ALLOC>
222/// my_FixedSizeArray<T,ALLOC>::~my_FixedSizeArray()
223/// {
224/// // Call destructor for each element
225/// for (int i = 0; i < d_length; ++i) {
226/// d_allocator.destroy(&d_array[i]);
227/// }
228///
229/// // Return memory to allocator.
230/// d_allocator.deallocate(d_array, d_length);
231/// }
232///
233/// // MANIPULATORS
234/// template<class T, class ALLOC>
235/// inline T& my_FixedSizeArray<T,ALLOC>::operator[](int i)
236/// {
237/// return d_array[i];
238/// }
239///
240/// // ACCESSORS
241/// template<class T, class ALLOC>
242/// inline
243/// const T& my_FixedSizeArray<T,ALLOC>::operator[](int i) const
244/// {
245/// return d_array[i];
246/// }
247///
248/// template<class T, class ALLOC>
249/// inline int my_FixedSizeArray<T,ALLOC>::length() const
250/// {
251/// return d_length;
252/// }
253///
254/// template<class T, class ALLOC>
255/// inline
256/// const ALLOC& my_FixedSizeArray<T,ALLOC>::allocator() const
257/// {
258/// return d_allocator;
259/// }
260///
261/// // FREE OPERATORS
262/// template<class T, class ALLOC>
263/// bool operator==(const my_FixedSizeArray<T,ALLOC>& lhs,
264/// const my_FixedSizeArray<T,ALLOC>& rhs)
265/// {
266/// if (lhs.length() != rhs.length()) {
267/// return false;
268/// }
269/// for (int i = 0; i < lhs.length(); ++i) {
270/// if (lhs[i] != rhs[i]) {
271/// return false;
272/// }
273/// }
274/// return true;
275/// }
276/// @endcode
277/// Now we declare an allocator mechanism. Our mechanism will be to simply call
278/// global `operator new` and `operator delete` functions, and count the number
279/// of blocks outstanding (allocated but not deallocated). Note that a more
280/// reusable implementation would take an underlying mechanism at construction.
281/// We keep things simple only for the sake of this example.
282/// @code
283/// // my_countingallocator.h
284///
285/// // ==========================
286/// // class my_CountingAllocator
287/// // ==========================
288///
289/// /// This concrete implementation of the `bslma::Allocator` protocol
290/// /// maintains some statistics of the number of blocks outstanding (i.e.,
291/// /// allocated but not yet deallocated).
292/// class my_CountingAllocator : public bslma::Allocator {
293///
294/// // DATA
295/// int d_blocksOutstanding;
296///
297/// public:
298/// // CREATORS
299///
300/// /// Create a counting allocator that uses the operators `new` and
301/// /// `delete` to supply and free memory.
302/// my_CountingAllocator();
303///
304/// // MANIPULATORS
305///
306/// /// Return a pointer to an uninitialized memory of the specified
307/// /// `size` (in bytes).
308/// virtual void *allocate(size_type size);
309///
310/// /// Return the memory at the specified `address` to this allocator.
311/// virtual void deallocate(void *address);
312///
313/// // ACCESSORS
314///
315/// /// Return the number of blocks outstanding (i.e., allocated but not
316/// /// yet deallocated by this counting allocator).
317/// int blocksOutstanding() const;
318/// };
319/// @endcode
320/// The implementation is really straightforward:
321/// @code
322/// // my_countingallocator.cpp
323///
324/// // --------------------------
325/// // class my_CountingAllocator
326/// // --------------------------
327///
328/// // CREATORS
329/// my_CountingAllocator::my_CountingAllocator()
330/// : d_blocksOutstanding(0)
331/// {
332/// }
333///
334/// // MANIPULATORS
335/// void *my_CountingAllocator::allocate(size_type size)
336/// {
337/// ++d_blocksOutstanding;
338/// return operator new(size);
339/// }
340///
341/// void my_CountingAllocator::deallocate(void *address)
342/// {
343/// --d_blocksOutstanding;
344/// operator delete(address);
345/// }
346///
347/// // ACCESSORS
348/// int my_CountingAllocator::blocksOutstanding() const
349/// {
350/// return d_blocksOutstanding;
351/// }
352/// @endcode
353/// Now we can create array objects with different allocator mechanisms. First
354/// we create an array, `a1`, using the default allocator and fill it with the
355/// values `[1 .. 5]`:
356/// @code
357/// int main() {
358///
359/// my_FixedSizeArray<int, bsl::allocator<int> > a1(5);
360/// assert(5 == a1.length());
361/// assert(bslma::Default::defaultAllocator() == a1.allocator());
362///
363/// for (int i = 0; i < a1.length(); ++i) {
364/// a1[i] = i + 1;
365/// }
366/// @endcode
367/// Then we create a copy of `a1` using the counting allocator. The values of
368/// `a1` and `a2` are equal, even though they have different allocation
369/// mechanisms.
370/// @code
371/// my_CountingAllocator countingAlloc;
372/// my_FixedSizeArray<int, bsl::allocator<int> > a2(a1,&countingAlloc);
373/// assert(a1 == a2);
374/// assert(a1.allocator() != a2.allocator());
375/// assert(&countingAlloc == a2.allocator());
376/// assert(1 == countingAlloc.blocksOutstanding())
377/// }
378/// @endcode
379/// @}
380/** @} */
381/** @} */
382
383/** @addtogroup bsl
384 * @{
385 */
386/** @addtogroup bslstl
387 * @{
388 */
389/** @addtogroup bslstl_allocator
390 * @{
391 */
392
393#include <bslscm_version.h>
394
395#include <bslma_bslallocator.h>
396
397
398
399
400
401#endif
402
403// ----------------------------------------------------------------------------
404// Copyright 2013 Bloomberg Finance L.P.
405//
406// Licensed under the Apache License, Version 2.0 (the "License");
407// you may not use this file except in compliance with the License.
408// You may obtain a copy of the License at
409//
410// http://www.apache.org/licenses/LICENSE-2.0
411//
412// Unless required by applicable law or agreed to in writing, software
413// distributed under the License is distributed on an "AS IS" BASIS,
414// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
415// See the License for the specific language governing permissions and
416// limitations under the License.
417// ----------------------------- END-OF-FILE ----------------------------------
418
419/** @} */
420/** @} */
421/** @} */
#define BSLS_IDENT(str)
Definition bsls_ident.h:195