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