BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bslma_allocatoradaptor.h
Go to the documentation of this file.
1/// @file bslma_allocatoradaptor.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bslma_allocatoradaptor.h -*-C++-*-
8#ifndef INCLUDED_BSLMA_ALLOCATORADAPTOR
9#define INCLUDED_BSLMA_ALLOCATORADAPTOR
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bslma_allocatoradaptor bslma_allocatoradaptor
15/// @brief Provide a polymorphic adaptor for STL-style allocators
16/// @addtogroup bsl
17/// @{
18/// @addtogroup bslma
19/// @{
20/// @addtogroup bslma_allocatoradaptor
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bslma_allocatoradaptor-purpose"> Purpose</a>
25/// * <a href="#bslma_allocatoradaptor-classes"> Classes </a>
26/// * <a href="#bslma_allocatoradaptor-description"> Description </a>
27/// * <a href="#bslma_allocatoradaptor-usage"> Usage </a>
28///
29/// # Purpose {#bslma_allocatoradaptor-purpose}
30/// Provide a polymorphic adaptor for STL-style allocators
31///
32/// # Classes {#bslma_allocatoradaptor-classes}
33/// AllocatorAdaptor<ALLOC>
34///
35/// @see
36///
37/// # Description {#bslma_allocatoradaptor-description}
38/// Within the BDE libraries, the prefered way to handle memory
39/// allocation is through a pointer to the polymorphic base class,
40/// `bslma::Allocator`. The use of a run-time polymorphism for the allocator
41/// has numerous advantages over the compile-time polymorphism used by the STL
42/// components. However, there are times when client code may have an
43/// STL-style allocator available and needs to use it with a BDE component.
44///
45/// This component provides a class template, `AllocatorAdaptor` that wraps the
46/// STL-style allocator in an object of class derived from `bslma::Allocator`.
47/// A pointer to the object can thus be used with any component that uses
48/// BDE-style memory allocation.
49///
50/// ## Usage {#bslma_allocatoradaptor-usage}
51///
52///
53/// Let's start with a simple class, `my::FilePath`, which allocates storage
54/// using a `bslma::Allocator`:
55/// @code
56/// #include <bslma_allocator.h>
57/// #include <bslma_default.h>
58/// #include <bsls_nullptr.h>
59///
60/// #include <cstring>
61/// #include <cstdlib>
62///
63/// namespace my {
64///
65/// /// Store the path of a file or directory.
66/// class FilePath {
67/// bslma::Allocator *d_allocator;
68/// char *d_data;
69///
70/// public:
71/// FilePath(bslma::Allocator* basicAllocator = 0 /* nullptr */)
72/// : d_allocator(bslma::Default::allocator(basicAllocator))
73/// , d_data(0 /* nullptr */) { }
74///
75/// FilePath(const char* s, bslma::Allocator* basicAllocator = 0)
76/// : d_allocator(bslma::Default::allocator(basicAllocator))
77/// {
78/// d_data =
79/// static_cast<char*>(d_allocator->allocate(std::strlen(s) + 1));
80/// std::strcpy(d_data, s);
81/// }
82///
83/// bslma::Allocator *getAllocator() const { return d_allocator; }
84///
85/// //...
86/// };
87///
88/// } // close namespace my
89/// @endcode
90/// Next, assume that an STL-allocator exists that uses memory exactly the way
91/// you need:
92/// @code
93/// template <class TYPE>
94/// class MagicAllocator {
95/// bool d_useMalloc;
96/// public:
97/// typedef TYPE value_type;
98/// typedef TYPE *pointer;
99/// typedef const TYPE *const_pointer;
100/// typedef unsigned size_type;
101/// typedef int difference_type;
102///
103/// template <class U>
104/// struct rebind {
105/// typedef MagicAllocator<U> other;
106/// };
107///
108/// explicit MagicAllocator(bool useMalloc = false)
109/// : d_useMalloc(useMalloc) { }
110///
111/// template <class U>
112/// MagicAllocator(const MagicAllocator<U>& other)
113/// : d_useMalloc(other.getUseMalloc()) { }
114///
115/// value_type *allocate(std::size_t n, void* = 0 /* nullptr */) {
116/// if (d_useMalloc)
117/// return (value_type*) std::malloc(n * sizeof(value_type));
118/// else
119/// return (value_type*) ::operator new(n * sizeof(value_type));
120/// }
121///
122/// void deallocate(value_type *p, std::size_t) {
123/// if (d_useMalloc)
124/// std::free(p);
125/// else
126/// ::operator delete(p);
127/// }
128///
129/// static size_type max_size() { return UINT_MAX / sizeof(TYPE); }
130///
131/// void construct(pointer p, const TYPE& value)
132/// { new((void *)p) TYPE(value); }
133///
134/// void destroy(pointer p) { p->~TYPE(); }
135///
136/// int getUseMalloc() const { return d_useMalloc; }
137/// };
138///
139/// template <class T, class U>
140/// inline
141/// bool operator==(const MagicAllocator<T>& a, const MagicAllocator<U>& b)
142/// {
143/// return a.getUseMalloc() == b.getUseMalloc();
144/// }
145///
146/// template <class T, class U>
147/// inline
148/// bool operator!=(const MagicAllocator<T>& a, const MagicAllocator<U>& b)
149/// {
150/// return a.getUseMalloc() != b.getUseMalloc();
151/// }
152/// @endcode
153/// Now, if we want to create a `FilePath` using a `MagicAllocator`, we
154/// need to adapt the `MagicAllocator` to the `bslma::Allocator` protocol.
155/// This is where `bslma::AllocatorAdaptor` comes in:
156/// @code
157/// int main()
158/// {
159/// MagicAllocator<char> ma(true);
160/// bslma::AllocatorAdaptor<MagicAllocator<char> >::Type maa(ma);
161///
162/// my::FilePath usrbin("/usr/local/bin", &maa);
163///
164/// assert(&maa == usrbin.getAllocator());
165/// assert(ma == maa.adaptedAllocator());
166///
167/// return 0;
168/// }
169/// @endcode
170/// @}
171/** @} */
172/** @} */
173
174/** @addtogroup bsl
175 * @{
176 */
177/** @addtogroup bslma
178 * @{
179 */
180/** @addtogroup bslma_allocatoradaptor
181 * @{
182 */
183
184#include <bslscm_version.h>
185
186#include <bslma_allocator.h>
187
188#include <bslmf_assert.h>
189#include <bslmf_issame.h>
190
191#include <bsls_alignmentutil.h>
193#include <bsls_keyword.h>
194
195
196
197namespace bslma {
198
199 // ===================================
200 // class template AllocatorAdaptor_Imp
201 // ===================================
202
203/// Component-private class. Do not use. This class provides the actual
204/// interface and implementaiton for `AllocatorAdaptor`, which inherits
205/// from it. The indirection is necessary so that
206/// `AllocatorAdaptor<Alloc<T>>` and `AllocatorAdaptor<Alloc<U>>` produce
207/// only one instantiation of this template:
208/// `AllocatorAdaptor_imp<Alloc<char>>`.
209///
210/// See @ref bslma_allocatoradaptor
211template <class STL_ALLOC>
213
215
216 // PRIVATE TYPES
217 typedef bsls::AlignmentUtil::MaxAlignedType MaxAlignedType;
218
219 // PRIVATE DATA
220 typename STL_ALLOC::template rebind<MaxAlignedType>::other d_stlAllocator;
221
222 // NOT ASSIGNABLE
223 AllocatorAdaptor_Imp& operator=(const AllocatorAdaptor_Imp&); // = delete
224
225 public:
226 // TYPES
228 typedef STL_ALLOC StlAllocatorType;
229
230 // CREATORS
231
232 /// Construct a polymorphic wrapper around a default-constructed
233 /// STL-style allocator.
234 AllocatorAdaptor_Imp(); // = default
235
236 /// Construct a polymorphic wrapper around a copy of the specified
237 /// `stla` STL-style allocator.
239
240#if defined(BSLS_COMPILERFEATURES_SUPPORT_DEFAULTED_FUNCTIONS)
241 /// Create an `AllocatorAdaptor_Imp` object that can allocate and
242 /// deallocate memory as if it were the specified `original` object.
243 AllocatorAdaptor_Imp(const AllocatorAdaptor_Imp& original) = default;
244#endif
245
246
247 /// Destroy this object and the STL-style allocator that it wraps.
249
250 // MANIPULATORS
251
252 /// Return a maximally-aligned block of memory no smaller than `size`
253 /// bytes allocated from the STL-style allocator that was supplied to
254 /// this object's constructor. Any exceptions thrown by the underlying
255 /// STL-style allocator are propagated out from this member.
257
258 /// Return the memory block at the specified `address` back to the
259 /// STL-allocator. If `address` is null, this funciton has no effect.
260 /// The behavior is undefined unless `address` was allocated using this
261 /// allocator object and has not already been deallocated.
263
264 // ACCESSORS
265
266 /// Return a copy of the STL allocator stored within this object.
267 STL_ALLOC adaptedAllocator() const;
268};
269
270 // ===============================
271 // class template AllocatorAdaptor
272 // ===============================
273
274#ifdef BSLS_COMPILERFEATURES_SUPPORT_ALIAS_TEMPLATES
275/// Polymorphic wrapper around an STL-style allocator. Note that
276/// `AllocatorAdaptor<A>::Type` is the same type regardless of whether or
277/// not the compiler supports alias templates. It should be used,
278/// therefore, whenever the exact type of the adaptor is important.
279template <class STL_ALLOC>
280using AllocatorAdaptor =
282#else
283/// Polymorphic wrapper around an object of the specified `STL_ALLOC`
284/// STL-style allocator template parameter. A pointer to an object of this
285/// class can thus be used with any component that uses BDE-style memory
286/// allocation. Note that `AllocatorAdaptor<A>::Type` is the same type
287/// regardless of whether or not the compiler supports alias templates. It
288/// should be used, therefore, whenever the exact type of the adaptor is
289/// important.
290template <class STL_ALLOC>
291class AllocatorAdaptor : public
292 AllocatorAdaptor_Imp<typename STL_ALLOC::template rebind<char>::other>
293{
294 typedef typename STL_ALLOC::template rebind<char>::other ReboundSTLAlloc;
295
296 // Not assignable
297 AllocatorAdaptor& operator=(const AllocatorAdaptor&); // = delete
298
299public:
300 // CREATORS
301
302 /// Constructs a polymorphic wrapper around a default-constructed
303 /// STL-style allocator.
304 AllocatorAdaptor(); // = default
305
306 /// Constructs a polymorphic wrapper around a copy of the specified
307 /// 'stla' STL-style allocator.
308 AllocatorAdaptor(const STL_ALLOC& stla);
309
312};
313#endif // BSLS_COMPILERFEATURES_SUPPORT_ALIAS_TEMPLATES
314
315} // close package namespace
316
317// ===========================================================================
318// TEMPLATE IMPLEMENTATION
319// ===========================================================================
320
321 // -----------------------------------
322 // class template AllocatorAdaptor_Imp
323 // -----------------------------------
324
325// CREATORS
326template <class STL_ALLOC>
327inline
332
333template <class STL_ALLOC>
334inline
336 const StlAllocatorType& stla)
337 : d_stlAllocator(stla)
338{
339}
340
341template <class STL_ALLOC>
342inline
346
347// MANIPULATORS
348template <class STL_ALLOC>
350{
351 BSLMF_ASSERT(sizeof(size_type) <= sizeof(MaxAlignedType));
352
353 // Compute number of 'MaxAlignedType' objects needed to make up 'size'
354 // bytes plus an extra one to hold the size.
355 size_type n = 1 + (size+sizeof(MaxAlignedType)-1) / sizeof(MaxAlignedType);
356 MaxAlignedType* p = d_stlAllocator.allocate(n);
357 *reinterpret_cast<size_type*>(p) = n;
358 return ++p;
359}
360
361template <class STL_ALLOC>
363{
364 MaxAlignedType *p = static_cast<MaxAlignedType*>(address);
365
366 // Extract size from slot before 'p'
367 size_type n = *reinterpret_cast<size_type*>(--p);
368 d_stlAllocator.deallocate(p, n);
369}
370
371// ACCESSORS
372template <class STL_ALLOC>
374{
375 return d_stlAllocator;
376}
377
378#ifndef BSLS_COMPILERFEATURES_SUPPORT_ALIAS_TEMPLATES
379
380 // -------------------------------
381 // class template AllocatorAdaptor
382 // -------------------------------
383
384// CREATORS
385template <class STL_ALLOC>
386inline
390
391template <class STL_ALLOC>
392inline
394 : bslma::AllocatorAdaptor_Imp<ReboundSTLAlloc>(stla)
395{
396}
397#endif // ! BSLS_COMPILERFEATURES_SUPPORT_ALIAS_TEMPLATES
398
399
400
401
402#endif // ! defined(INCLUDED_BSLMA_ALLOCATORADAPTOR)
403
404// ----------------------------------------------------------------------------
405// Copyright 2013 Bloomberg Finance L.P.
406//
407// Licensed under the Apache License, Version 2.0 (the "License");
408// you may not use this file except in compliance with the License.
409// You may obtain a copy of the License at
410//
411// http://www.apache.org/licenses/LICENSE-2.0
412//
413// Unless required by applicable law or agreed to in writing, software
414// distributed under the License is distributed on an "AS IS" BASIS,
415// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
416// See the License for the specific language governing permissions and
417// limitations under the License.
418// ----------------------------- END-OF-FILE ----------------------------------
419
420/** @} */
421/** @} */
422/** @} */
Definition bslma_allocatoradaptor.h:212
STL_ALLOC StlAllocatorType
Definition bslma_allocatoradaptor.h:228
AllocatorAdaptor_Imp Type
Definition bslma_allocatoradaptor.h:227
Definition bslma_allocatoradaptor.h:293
AllocatorAdaptor(const AllocatorAdaptor &)
Definition bslma_allocator.h:457
std::size_t size_type
Definition bslma_allocator.h:499
STL_ALLOC adaptedAllocator() const
Return a copy of the STL allocator stored within this object.
Definition bslma_allocatoradaptor.h:373
AllocatorAdaptor_Imp()
Definition bslma_allocatoradaptor.h:328
AllocatorAdaptor_Imp(const StlAllocatorType &stla)
Definition bslma_allocatoradaptor.h:335
AllocatorAdaptor()
Definition bslma_allocatoradaptor.h:387
~AllocatorAdaptor_Imp() BSLS_KEYWORD_OVERRIDE
Destroy this object and the STL-style allocator that it wraps.
Definition bslma_allocatoradaptor.h:343
void deallocate(void *address) BSLS_KEYWORD_OVERRIDE
Definition bslma_allocatoradaptor.h:362
void * allocate(size_type size) BSLS_KEYWORD_OVERRIDE
Definition bslma_allocatoradaptor.h:349
#define BSLMF_ASSERT(expr)
Definition bslmf_assert.h:229
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
#define BSLS_KEYWORD_OVERRIDE
Definition bsls_keyword.h:653
Definition balxml_encoderoptions.h:68
Definition bslmf_issame.h:146
AlignmentToType< BSLS_MAX_ALIGNMENT >::Type MaxAlignedType
Definition bsls_alignmentutil.h:282