BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bdlma_localsequentialallocator.h
Go to the documentation of this file.
1/// @file bdlma_localsequentialallocator.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bdlma_localsequentialallocator.h -*-C++-*-
8#ifndef INCLUDED_BDLMA_LOCALSEQUENTIALALLOCATOR
9#define INCLUDED_BDLMA_LOCALSEQUENTIALALLOCATOR
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bdlma_localsequentialallocator bdlma_localsequentialallocator
15/// @brief Provide an efficient managed allocator using a local buffer.
16/// @addtogroup bdl
17/// @{
18/// @addtogroup bdlma
19/// @{
20/// @addtogroup bdlma_localsequentialallocator
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bdlma_localsequentialallocator-purpose"> Purpose</a>
25/// * <a href="#bdlma_localsequentialallocator-classes"> Classes </a>
26/// * <a href="#bdlma_localsequentialallocator-description"> Description </a>
27/// * <a href="#bdlma_localsequentialallocator-usage"> Usage </a>
28/// * <a href="#bdlma_localsequentialallocator-example-1-recommended-usage"> Example 1: Recommended Usage </a>
29///
30/// # Purpose {#bdlma_localsequentialallocator-purpose}
31/// Provide an efficient managed allocator using a local buffer.
32///
33/// # Classes {#bdlma_localsequentialallocator-classes}
34///
35/// - bdlma::LocalSequentialAllocator: allocator using a local buffer
36///
37/// @see bdlma_bufferedsequentialallocator
38///
39/// # Description {#bdlma_localsequentialallocator-description}
40/// This component provides a concrete mechanism,
41/// `bdlma::LocalSequentialAllocator`, that implements the
42/// `bdlma::ManagedAllocator` protocol to very efficiently allocate
43/// heterogeneous memory blocks (of varying, user-specified sizes) from a local
44/// buffer. Note that it derives from `bdlma::BufferedSequentialAllocator` so
45/// that the implementations of `allocate`, `deallocate`, and `release` don't
46/// need to be instantiated for each user-specified size.
47/// @code
48/// ,-------------------------------.
49/// ( bdlma::LocalSequentialAllocator )
50/// `-------------------------------'
51/// | ctor
52/// V
53/// ,----------------------------------.
54/// ( bdlma::BufferedSequentialAllocator )
55/// `----------------------------------'
56/// | ctor/dtor
57/// | allocate
58/// | deallocate
59/// | release
60/// | rewind
61/// V
62/// ,-----------------------.
63/// ( bdlma::ManagedAllocator )
64/// `-----------------------'
65/// | release = 0
66/// V
67/// ,----------------.
68/// ( bslma::Allocator )
69/// `----------------'
70/// allocate = 0
71/// deallocate = 0
72/// @endcode
73/// If an allocation request exceeds the remaining free memory space in the
74/// local buffer, the allocator will fall back to a sequence of
75/// dynamically-allocated buffers. The `release` method releases all memory
76/// allocated through the allocator, as does the destructor. Note that, even
77/// though a `deallocate` method is available, it has no effect: individually
78/// allocated memory blocks cannot be separately deallocated.
79///
80/// `bdlma::LocalSequentialAllocator` is typically used when users have a
81/// reasonable estimation of the amount of memory needed. This amount of memory
82/// would then be created directly on the program stack, and used as the local
83/// buffer by this allocator for very fast memory allocation. Whilst the buffer
84/// has sufficient capacity, memory allocations will not trigger *any* dynamic
85/// memory allocation, will have optimal locality of reference, and will not
86/// require deallocation upon destruction.
87///
88/// Once the local buffer is exhausted, subsequent allocation requests require
89/// dynamic memory allocation, and the performance of the allocator degrades.
90///
91/// The main difference between a `bdlma::LocalSequentialAllocator` and a
92/// `bdlma::BufferedSequentialAllocator` is that this class internally maintains
93/// a buffer, rather than being given one at construction time.
94///
95/// ## Usage {#bdlma_localsequentialallocator-usage}
96///
97///
98/// This section illustrates intended use of this component.
99///
100/// ### Example 1: Recommended Usage {#bdlma_localsequentialallocator-example-1-recommended-usage}
101///
102///
103/// Suppose we have a function which takes a map of items to update in some
104/// database:
105/// @code
106/// typedef bsl::string DatabaseKey;
107/// typedef bsl::string DatabaseValue;
108///
109/// void updateRecords_1(const bsl::map<DatabaseKey, DatabaseValue>& values)
110/// {
111/// for (bsl::map<DatabaseKey, DatabaseValue>::const_iterator
112/// it = values.begin(), end = values.end();
113/// it != end;
114/// ++it) {
115/// bsl::stringbuf stringBuf;
116/// bsl::ostream ostr(&stringBuf);
117///
118/// ostr << "UPDATE myTable SET myValue = '" << it->first << "' WHERE "
119/// "myKey = '" << it->second << "'";
120///
121/// // execute query using 'stringBuf.str()'
122/// }
123/// }
124/// @endcode
125/// We call this method a lot, and after profiling, we notice that it's
126/// contributing a significant proportion of time, due to the allocations it is
127/// making. We decide to see whether a LocalSequentialAllocator would help.
128///
129/// First, use a `bslma::TestAllocator` to track the typical memory usage:
130/// @code
131/// void updateRecords_2(const bsl::map<DatabaseKey, DatabaseValue>& values)
132/// {
133/// bslma::TestAllocator ta;
134///
135/// for (bsl::map<DatabaseKey, DatabaseValue>::const_iterator
136/// it = values.begin(), end = values.end();
137/// it != end;
138/// ++it) {
139/// bsl::stringbuf stringBuf(&ta);
140/// bsl::ostream ostr(&stringBuf);
141///
142/// ostr << "UPDATE myTable SET myValue = '" << it->first << "' WHERE "
143/// "myKey = '" << it->second << "'";
144///
145/// // execute query using 'stringBuf.str()'
146///
147/// bsl::cout << "In use: " << ta.numBytesInUse() << '\n';
148/// }
149///
150/// bsl::cout << "Max: " << ta.numBytesMax() << '\n';
151/// }
152/// @endcode
153/// Then we run our program again, and observe the following output:
154/// @code
155/// In use: 77
156/// In use: 77
157/// In use: 77
158/// In use: 77
159/// In use: 77
160/// Max: 129
161/// @endcode
162/// It looks like 129 is a good choice for the size of our allocator, so we go
163/// with that:
164/// @code
165/// void updateRecords_3(const bsl::map<DatabaseKey, DatabaseValue>& values)
166/// {
167/// bdlma::LocalSequentialAllocator<129> lsa;
168///
169/// for (bsl::map<DatabaseKey, DatabaseValue>::const_iterator
170/// it = values.begin(), end = values.end();
171/// it != end;
172/// ++it) {
173/// lsa.release();
174///
175/// bsl::stringbuf stringBuf(&lsa);
176/// bsl::ostream ostr(&stringBuf);
177///
178/// ostr << "UPDATE myTable SET myValue = '" << it->first << "' WHERE "
179/// "myKey = '" << it->second << "'";
180///
181/// // execute query using 'stringBuf.str()'
182/// }
183/// }
184/// @endcode
185/// Note that we release at the end of every iteration, as the deallocate method
186/// is a no-op, so without this, subsequent memory would be allocated from the
187/// default allocator (or the allocator passed to `bsa` at construction).
188///
189/// Finally, we re-profile our code to determine whether the addition of a
190/// `LocalSequentialAllocator` helped.
191/// @}
192/** @} */
193/** @} */
194
195/** @addtogroup bdl
196 * @{
197 */
198/** @addtogroup bdlma
199 * @{
200 */
201/** @addtogroup bdlma_localsequentialallocator
202 * @{
203 */
204
205#include <bdlscm_version.h>
206
208
209#include <bslma_allocator.h>
210
211
212namespace bdlma {
213
214 // ==============================
215 // class LocalSequentialAllocator
216 // ==============================
217
218/// This class implements the `ManagedAllocator` protocol to provide a fast
219/// allocator that dispenses heterogeneous blocks of memory (of varying,
220/// user-specified sizes) from a local buffer whose capacity is the
221/// specified `t_SIZE` (in bytes). If an allocation request exceeds the
222/// remaining free memory space in the local buffer, memory will be supplied
223/// by an (optional) allocator supplied at construction; if no allocator is
224/// supplied, the currently installed default allocator is used. This class
225/// is *exception* *neutral*; if memory cannot be allocated, the behavior is
226/// defined by the (optional) allocator supplied at construction.
227///
228/// See @ref bdlma_localsequentialallocator
229template <int t_SIZE>
231
232 // PRIVATE TYPES
234#if !defined(BSLS_COMPILERFEATURES_SUPPORT_ALIGNAS)
235 typedef bsls::AlignmentToType<
236 bsls::AlignmentUtil::BSLS_MAX_ALIGNMENT>::Type AlignmentType;
237#endif
238
239 // DATA
240
241
242#if defined(BSLS_COMPILERFEATURES_SUPPORT_ALIGNAS)
243 // The C++11 implementation uses the 'alignas' keyword to ensure the
244 // alignment of 'd_buffer'.
246#else
247 /// This anonymous union is `bsls::AlignedBuffer`, but typed out again
248 /// so that extra template instantiations are avoided. The C++03
249 /// implementation uses a union data member to ensure the alignment of
250 /// `d_buffer`.
251 union {
252 char d_buffer[t_SIZE];
253 AlignmentType d_align;
254 };
255#endif
256
257 private:
258 // NOT IMPLEMENTED
260 LocalSequentialAllocator& operator=(
261 // const LocalSequentialAllocator&) = delete;
262
263 public:
264 // CREATORS
265
266 /// Create a local sequential allocator for allocating memory blocks
267 /// from a local buffer having the specified `t_SIZE` (in bytes).
268 /// Optionally specify a `basicAllocator` used to supply memory should
269 /// the capacity of the local buffer be exhausted. If `basicAllocator`
270 /// is 0, the currently installed default allocator is used.
271 explicit LocalSequentialAllocator(bslma::Allocator *basicAllocator = 0);
272
273 virtual ~LocalSequentialAllocator() = default;
274 // Destroy this local sequential allocator. All memory allocated from
275 // this allocator is released.
276};
277
278// ============================================================================
279// INLINE DEFINITIONS
280// ============================================================================
281
282 // ------------------------------
283 // class LocalSequentialAllocator
284 // ------------------------------
285
286// CREATORS
287template <int t_SIZE>
288inline
289LocalSequentialAllocator<t_SIZE>::LocalSequentialAllocator(
290 bslma::Allocator *basicAllocator)
291: AllocatorBase(this->d_buffer, t_SIZE, basicAllocator)
292{
293}
294
295} // close package namespace
296
297
298#endif
299
300// ----------------------------------------------------------------------------
301// Copyright 2015 Bloomberg Finance L.P.
302//
303// Licensed under the Apache License, Version 2.0 (the "License");
304// you may not use this file except in compliance with the License.
305// You may obtain a copy of the License at
306//
307// http://www.apache.org/licenses/LICENSE-2.0
308//
309// Unless required by applicable law or agreed to in writing, software
310// distributed under the License is distributed on an "AS IS" BASIS,
311// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
312// See the License for the specific language governing permissions and
313// limitations under the License.
314// ----------------------------- END-OF-FILE ----------------------------------
315
316/** @} */
317/** @} */
318/** @} */
Definition bdlma_bufferedsequentialallocator.h:265
Definition bdlma_localsequentialallocator.h:230
AlignmentType d_align
Definition bdlma_localsequentialallocator.h:253
char d_buffer[t_SIZE]
Definition bdlma_localsequentialallocator.h:252
Definition bslma_allocator.h:457
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
Definition bdlma_alignedallocator.h:276
Definition balxml_encoderoptions.h:68
Definition bsls_alignmenttotype.h:317
@ BSLS_MAX_ALIGNMENT
Definition bsls_alignmentutil.h:275