BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bslma_bufferallocator.h
Go to the documentation of this file.
1/// @file bslma_bufferallocator.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bslma_bufferallocator.h -*-C++-*-
8#ifndef INCLUDED_BSLMA_BUFFERALLOCATOR
9#define INCLUDED_BSLMA_BUFFERALLOCATOR
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bslma_bufferallocator bslma_bufferallocator
15/// @brief Support efficient memory allocations from a user-supplied buffer.
16/// @addtogroup bsl
17/// @{
18/// @addtogroup bslma
19/// @{
20/// @addtogroup bslma_bufferallocator
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bslma_bufferallocator-purpose"> Purpose</a>
25/// * <a href="#bslma_bufferallocator-classes"> Classes </a>
26/// * <a href="#bslma_bufferallocator-description"> Description </a>
27/// * <a href="#bslma_bufferallocator-alignment-strategy"> Alignment Strategy </a>
28/// * <a href="#bslma_bufferallocator-usage"> Usage </a>
29///
30/// # Purpose {#bslma_bufferallocator-purpose}
31/// Support efficient memory allocations from a user-supplied buffer.
32///
33/// @deprecated Use @ref bdlma_bufferedsequentialallocator instead.
34///
35/// # Classes {#bslma_bufferallocator-classes}
36///
37/// - bslma::BufferAllocator: memory allocator from user-supplied buffer
38///
39/// @see bdlma_bufferedsequentialallocator
40///
41/// # Description {#bslma_bufferallocator-description}
42/// This component provides an allocator, `bslma::BufferAllocator`,
43/// that implements the `bslma::Allocator` protocol and sequentially allocates
44/// memory blocks from a fixed-size buffer that is supplied by the user at
45/// construction. If an allocation request exceeds the remaining space in the
46/// buffer, the return value is the result of invoking an optional callback
47/// function that was supplied at construction, or zero if no callback was
48/// specified. This component also provides static utility functions for
49/// allocating memory directly from a user-specified buffer:
50/// @code
51/// ,----------------------.
52/// ( bslma::BufferAllocator )
53/// `----------------------'
54/// | ctor
55/// V
56/// ,----------------.
57/// ( bslma::Allocator )
58/// `----------------'
59/// allocate
60/// deallocate
61/// dtor
62/// @endcode
63///
64/// ## Alignment Strategy {#bslma_bufferallocator-alignment-strategy}
65///
66///
67/// The `bslma::BufferAllocator` allocates memory using one of the two alignment
68/// strategies: 1) MAXIMUM ALIGNMENT or 2) NATURAL ALIGNMENT.
69///
70/// 1. MAXIMUM ALIGNMENT: This strategy always allocates memory aligned with the
71/// most restrictive alignment on the host platform. The value is defined in
72/// `bsls::AlignmentUtil::BSLS_MAX_ALIGNMENT`.
73/// 2. NATURAL ALIGNMENT: This strategy allocates memory whose alignment depends
74/// on the requested number of bytes. An object of a fundamental type
75/// (`int`, etc.) is *naturally* *aligned* when it's size evenly divides its
76/// address. An object of an aggregate type has natural alignment if the
77/// alignment of the most-restrictively aligned sub-object evenly divides the
78/// address of the aggregate. Natural alignment is always at least as
79/// restrictive as the compiler's required alignment. When only the size of
80/// an aggregate is known, and not its composition, we compute the alignment
81/// by finding the largest integral power of 2 (up to and including
82/// `bsls::AlignmentUtil::BSLS_MAX_ALIGNMENT`) that divides the requested
83/// (non-zero) number of bytes. This computed alignment is guaranteed to be
84/// at least as restrictive as any sub-object within the aggregate.
85///
86/// ## Usage {#bslma_bufferallocator-usage}
87///
88///
89/// The `bslma::BufferAllocator` class defined in this component is commonly
90/// used to allocate memory from a static buffer that does not require
91/// "deletion". The following snippet of code creates an array that obtains its
92/// memory from a fixed-sized buffer, but through the `bslma::Allocator`
93/// protocol:
94/// @code
95/// // my_shortarray.h
96///
97/// // ...
98///
99/// namespace bslma { class Allocator; }
100///
101/// class my_ShortArray {
102/// short *d_array_p; // dynamically-allocated array of
103/// // `short` integers
104///
105/// int d_size; // physical size of `d_array_p`
106///
107/// int d_length; // logical length of `d_array_p`
108///
109/// bslma::Allocator *d_allocator_p; // memory allocator (held, not owned)
110///
111/// private:
112/// // PRIVATE MANIPULATORS
113/// void increaseSize(); // Increase the capacity by at least one element.
114///
115/// public:
116/// // CREATORS
117///
118/// /// Create an empty array using the specified `basicAllocator` to
119/// /// supply memory.
120/// my_ShortArray(bslma::Allocator *basicAllocator);
121/// // ...
122///
123/// ~my_ShortArray();
124/// void append(short value);
125/// const short& operator[](int index) const { return d_array_p[index]; }
126/// int length() const { return d_length; }
127/// };
128/// @endcode
129/// The implementation of `my_ShortArray` is as follows:
130/// @code
131/// // my_shortarray.cpp
132/// #include <my_shortarray.h>
133///
134/// enum { INITIAL_SIZE = 1, GROW_FACTOR = 2 };
135/// // ...
136///
137/// my_ShortArray::my_ShortArray(bslma::Allocator *basicAllocator)
138/// : d_size(INITIAL_SIZE)
139/// , d_length(0)
140/// , d_allocator_p(basicAllocator)
141/// {
142/// assert(d_allocator_p);
143/// d_array_p =
144/// (short *) d_allocator_p->allocate(d_size * sizeof *d_array_p);
145/// }
146///
147/// my_ShortArray::~my_ShortArray()
148/// {
149/// // CLASS INVARIANTS
150/// assert(d_array_p);
151/// assert(0 <= d_size);
152/// assert(0 <= d_length); assert(d_length <= d_size);
153/// assert(d_allocator_p);
154///
155/// d_allocator_p->deallocate(d_array_p);
156/// }
157///
158/// inline
159/// void my_ShortArray::append(short value)
160/// {
161/// if (d_length >= d_size) {
162/// increaseSize();
163/// }
164/// d_array_p[d_length++] = value;
165/// }
166///
167/// /// Reallocate memory in the specified `array` to the specified
168/// /// `newSize` using the specified `basicAllocator` or global new
169/// /// operator. The specified `length` number of leading elements are
170/// /// preserved. Since the class invariant requires that the physical
171/// /// capacity of the container may grow but never shrink, the behavior
172/// /// is undefined unless length <= newSize.
173/// static
174/// void reallocate(short **array, int newSize, int length,
175/// bslma::Allocator *basicAllocator)
176/// {
177/// assert(array);
178/// assert(1 <= newSize);
179/// assert(0 <= length);
180/// assert(length <= newSize); // enforce class invariant
181/// assert(basicAllocator);
182///
183/// short *tmp = *array; // support exception neutrality
184/// *array = (short *) basicAllocator->allocate(newSize * sizeof **array);
185///
186/// // COMMIT POINT
187///
188/// memcpy(*array, tmp, length * sizeof **array);
189/// basicAllocator->deallocate(tmp);
190/// }
191///
192/// void my_ShortArray::increaseSize()
193/// {
194/// int proposedNewSize = d_size * GROW_FACTOR; // reallocate can throw
195/// assert(proposedNewSize > d_length);
196/// reallocate(&d_array_p, proposedNewSize, d_length, d_allocator_p);
197/// d_size = proposedNewSize; // we're committed
198/// }
199/// // ...
200/// @endcode
201/// Use buffer allocator to allocate memory for `my_ShortArray` as follows:
202/// @code
203/// void *callbackFunc(int /* size */)
204/// {
205/// std::cerr << "Buffer allocator out of memory." << std::endl;
206/// exit(-1);
207/// return (void *) 0;
208/// }
209/// // ...
210///
211/// int main(int argc, char *argv[])
212/// {
213/// // ...
214/// static char memory[1024]; // No alignment issue; see below.
215/// bslma::BufferAllocator allocator(memory, sizeof memory, callbackFunc);
216///
217/// my_ShortArray mA(allocator);
218/// const my_ShortArray& A = mA;
219/// mA.append(123);
220/// mA.append(456);
221/// // ...
222/// }
223/// @endcode
224/// Note that in the `main` function above, `memory` does not need to be aligned
225/// because `bslma::BufferAllocator::allocate` internally performs alignment for
226/// each requested memory block based on the allocator's alignment strategy.
227/// @}
228/** @} */
229/** @} */
230
231/** @addtogroup bsl
232 * @{
233 */
234/** @addtogroup bslma
235 * @{
236 */
237/** @addtogroup bslma_bufferallocator
238 * @{
239 */
240
241#ifdef BDE_OPENSOURCE_PUBLICATION // DEPRECATED
242#error "bslma_bufferallocator is deprecated"
243#endif
244#include <bslscm_version.h>
245
246#include <bslma_allocator.h>
247
248#include <bsls_keyword.h>
249
250
251
252namespace bslma {
253
254 // =====================
255 // class BufferAllocator
256 // =====================
257
258/// This `class` provides a concrete buffer allocator that implements the
259/// `Allocator` interface, and allocates memory blocks from a fixed-size
260/// buffer that is supplied by the user at construction. The allocator can
261/// supply memory that can be maximally (default) or naturally aligned.
262///
263/// See @ref bslma_bufferallocator
265
266 public:
267 // TYPES
268
269 /// `AllocCallback` is an alias for (the address of) a function that
270 /// takes an integer argument and returns `void *`.
271 typedef void *(*AllocCallback)(int);
272
273 /// Types of alignment strategy to allocate memory.
275
276 MAXIMUM_ALIGNMENT, // Default. Return memory on maximally-aligned
277 // boundary
278 // 'bsls::AlignmentUtil::BSLS_MAX_ALIGNMENT' (as
279 // required for ANSI standard allocators).
280
281 NATURAL_ALIGNMENT // Return memory aligned on a boundary that is the
282 // largest power of two dividing the requested size
283 // (up to
284 // 'bsls::AlignmentUtil::BSLS_MAX_ALIGNMENT').
285 };
286
287 private:
288 // DATA
289 AlignmentStrategy d_strategy; // strategy to use for alignment
290 int d_cursor; // position of the remaining free space
291 char *d_buffer_p; // buffer for allocating memory
292 int d_bufferSize; // size of the buffer
293 AllocCallback d_allocCallback; // function handling buffer overflow
294
295 // NOT IMPLEMENTED
297 BufferAllocator& operator=(const BufferAllocator&);
298
299 public:
300 // CLASS METHODS
301
302 /// Allocate a memory block of the specified `size` from the specified
303 /// `buffer` at the specified `cursor` position. Return the address of
304 /// the allocated memory block if `buffer` contains enough available
305 /// memory, and `null` otherwise. The `cursor` is set to the index of
306 /// the next available byte in `buffer` after the allocation. Use the
307 /// specified alignment `strategy` (or `alignment` value) to allocate
308 /// memory. If `size` is 0, do not allocate memory and return zero.
309 /// The behavior is undefined unless `0 < = bufSize`, `0 <= size`,
310 /// `0 < alignment <= bsls::AlignmentUtil::BSLS_MAX_ALIGNMENT`, and
311 /// alignment is an integral power of 2.
312 static void *allocateFromBuffer(int *cursor,
313 char *buffer,
314 size_type bufSize,
315 size_type size,
316 AlignmentStrategy strategy);
317 static void *allocateFromBuffer(int *cursor,
318 char *buffer,
319 size_type bufSize,
320 size_type size,
321 int alignment);
322
323 // CREATORS
324
325 /// Create a buffer allocator for allocating memory blocks from the
326 /// specified `buffer` of the specified `bufSize`. Optionally specify a
327 /// callback function `allocCallback` that is invoked when a call to
328 /// `allocate` cannot be fulfilled from `buffer`. Note that maximum
329 /// alignment is used when allocating memory.
330 BufferAllocator(char *buffer,
331 size_type bufSize,
332 AllocCallback allocCallback = 0);
333
334 /// Create a buffer allocator for allocating memory blocks from the
335 /// specified `buffer` of the specified `bufSize`. Use the specified
336 /// alignment `strategy` to allocate memory. Optionally specify a
337 /// callback function `allocCallback` that is invoked when a call to
338 /// `allocate` cannot be fulfilled from `buffer`.
339 BufferAllocator(char *buffer,
340 size_type bufSize,
341 AlignmentStrategy strategy,
342 AllocCallback allocCallback = 0);
343
344 /// Destroy this buffer allocator.
346
347 // MANIPULATORS
348
349 /// Return a newly allocated block of memory of (at least) the specified
350 /// positive `size` (in bytes). If `size` is 0, a null pointer is
351 /// returned with no other effect. If this allocator cannot return the
352 /// requested number of bytes, then it will return the result of
353 /// invoking an optional callback function (supplied at construction);
354 /// if no callback function was specified, throw a `std::bad_alloc`
355 /// exception in an exception-enabled build, or else abort the program
356 /// in a non-exception build. The behavior is undefined unless
357 /// `0 <= size`. Note that the alignment of the address returned
358 /// depends on the alignment strategy (`MAXIMUM_ALIGNMENT` or
359 /// `NATURAL_ALIGNMENT`) specified at construction of this buffer
360 /// allocator. Also note that it is up to the callback function whether
361 /// to return zero or throw an exception if this buffer allocator is
362 /// unable to satisfy the request.
364
365 /// This function has no effect for this buffer allocator.
366 void deallocate(void *address) BSLS_KEYWORD_OVERRIDE;
367
368 // ACCESSORS
369
370 /// Write formatted debugging information to `stdout` describing the
371 /// internal state of this buffer allocator.
372 void print() const;
373};
374
375// ============================================================================
376// INLINE DEFINITIONS
377// ============================================================================
378
379 // ---------------------
380 // class BufferAllocator
381 // ---------------------
382
383// CREATORS
384inline
386 size_type bufSize,
387 AllocCallback allocCallback)
388: d_strategy(MAXIMUM_ALIGNMENT)
389, d_cursor(0)
390, d_buffer_p(buffer)
391, d_bufferSize(static_cast<int>(bufSize))
392, d_allocCallback(allocCallback)
393{
394}
395
396inline
397BufferAllocator::BufferAllocator(char *buffer,
398 size_type bufSize,
399 AlignmentStrategy strategy,
400 AllocCallback allocCallback)
401: d_strategy(strategy)
402, d_cursor(0)
403, d_buffer_p(buffer)
404, d_bufferSize(static_cast<int>(bufSize))
405, d_allocCallback(allocCallback)
406{
407}
408
409// MANIPULATORS
410inline
412{
413}
414
415} // close package namespace
416
417#ifndef BDE_OPENSOURCE_PUBLICATION // BACKWARD_COMPATIBILITY
418// ============================================================================
419// BACKWARD COMPATIBILITY
420// ============================================================================
421
422/// This alias is defined for backward compatibility.
424#endif // BDE_OPENSOURCE_PUBLICATION -- BACKWARD_COMPATIBILITY
425
426
427
428#endif
429
430// ----------------------------------------------------------------------------
431// Copyright 2013 Bloomberg Finance L.P.
432//
433// Licensed under the Apache License, Version 2.0 (the "License");
434// you may not use this file except in compliance with the License.
435// You may obtain a copy of the License at
436//
437// http://www.apache.org/licenses/LICENSE-2.0
438//
439// Unless required by applicable law or agreed to in writing, software
440// distributed under the License is distributed on an "AS IS" BASIS,
441// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
442// See the License for the specific language governing permissions and
443// limitations under the License.
444// ----------------------------- END-OF-FILE ----------------------------------
445
446/** @} */
447/** @} */
448/** @} */
Definition bslma_allocator.h:457
std::size_t size_type
Definition bslma_allocator.h:499
Definition bslma_bufferallocator.h:264
AlignmentStrategy
Types of alignment strategy to allocate memory.
Definition bslma_bufferallocator.h:274
@ NATURAL_ALIGNMENT
Definition bslma_bufferallocator.h:281
@ MAXIMUM_ALIGNMENT
Definition bslma_bufferallocator.h:276
static void * allocateFromBuffer(int *cursor, char *buffer, size_type bufSize, size_type size, AlignmentStrategy strategy)
void * allocate(size_type size) BSLS_KEYWORD_OVERRIDE
static void * allocateFromBuffer(int *cursor, char *buffer, size_type bufSize, size_type size, int alignment)
void deallocate(void *address) BSLS_KEYWORD_OVERRIDE
This function has no effect for this buffer allocator.
Definition bslma_bufferallocator.h:411
void *(* AllocCallback)(int)
Definition bslma_bufferallocator.h:271
~BufferAllocator() BSLS_KEYWORD_OVERRIDE
Destroy this buffer allocator.
bslma::BufferAllocator bslma_BufferAllocator
This alias is defined for backward compatibility.
Definition bslma_bufferallocator.h:423
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
#define BSLS_KEYWORD_OVERRIDE
Definition bsls_keyword.h:653
Definition balxml_encoderoptions.h:68