BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bdlma_aligningallocator.h
Go to the documentation of this file.
1/// @file bdlma_aligningallocator.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bdlma_aligningallocator.h -*-C++-*-
8#ifndef INCLUDED_BDLMA_ALIGNINGALLOCATOR
9#define INCLUDED_BDLMA_ALIGNINGALLOCATOR
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id$")
13
14/// @defgroup bdlma_aligningallocator bdlma_aligningallocator
15/// @brief Provide an allocator-wrapper to allocate with a minimum alignment.
16/// @addtogroup bdl
17/// @{
18/// @addtogroup bdlma
19/// @{
20/// @addtogroup bdlma_aligningallocator
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bdlma_aligningallocator-purpose"> Purpose</a>
25/// * <a href="#bdlma_aligningallocator-classes"> Classes </a>
26/// * <a href="#bdlma_aligningallocator-description"> Description </a>
27/// * <a href="#bdlma_aligningallocator-usage"> Usage </a>
28/// * <a href="#bdlma_aligningallocator-example-1-using-bdlma-aligningallocator"> Example 1: Using bdlma::AligningAllocator </a>
29///
30/// # Purpose {#bdlma_aligningallocator-purpose}
31/// Provide an allocator-wrapper to allocate with a minimum alignment.
32///
33/// # Classes {#bdlma_aligningallocator-classes}
34///
35/// - bdlma::AligningAllocator: wrapper to align memory allocation
36///
37/// @see
38///
39/// # Description {#bdlma_aligningallocator-description}
40/// This component defines a concrete allocator implementation,
41/// `bdlma::AligningAllocator`, providing the ability to allocate memory with a
42/// minimum alignment specified at the construction of the allocator. The
43/// following inheritance diagram shows the classes involved and their methods:
44/// @code
45/// ,------------------------.
46/// ( bdlma::AligningAllocator )
47/// `------------------------'
48/// | ctor/dtor
49/// |
50/// V
51/// ,----------------.
52/// ( bslma::Allocator )
53/// `----------------'
54/// allocate
55/// deallocate
56/// @endcode
57/// The `AligningAllocator` is supplied an allocator at construction, and
58/// ensures that memory returned by `allocate` meets a minimum alignment
59/// requirement. This may be useful in situations where a user needs to adapt
60/// an allocator supplying only natural alignment to software expecting an
61/// allocator with a higher alignment guarantee. The allocator supplied to an
62/// `AligningAllocator` at construction is held, not owned.
63///
64/// The allocator supplied to the aligning allocator must employ at least the
65/// natural alignment strategy (see @ref bsls_alignment ). Specifically, the
66/// aligning allocator will fail to properly align memory if the allocator
67/// passed to it employs the 1-byte alignment strategy.
68///
69/// Note that in order to provide the requested alignment an `AligningAllocator`
70/// will need to always overallocate memory from the underlying allocator. This
71/// can "waste" space equal to the alignment plus some extra bytes for
72/// bookkeeping information. For small allocations with large alignment values
73/// this waste can be very impactful. In general, this means this component
74/// should be used with small alignments or with larger allocations.
75///
76/// ## Usage {#bdlma_aligningallocator-usage}
77///
78///
79/// This section illustrates intended use of this component.
80///
81/// ### Example 1: Using bdlma::AligningAllocator {#bdlma_aligningallocator-example-1-using-bdlma-aligningallocator}
82///
83///
84/// Suppose we are dealing with an externally supplied library function that
85/// creates a linked list of null-terminated strings, and we want to use a
86/// default-constructed buffered sequential allocator for memory allocation.
87///
88/// First, the externally supplied library defines the `struct` describing a
89/// node in the linked list:
90/// @code
91/// struct Node {
92/// // This 'struct' describes one node in a linked list containing
93/// // strings.
94///
95/// Node *d_next;
96/// char d_string[1];
97///
98/// // CLASS METHODS
99/// static
100/// bsl::size_t sizeNeededForString(const char *string)
101/// // Return the size in bytes needed to store a 'Node' containing a
102/// // copy of the specified 'string'.
103/// {
104/// Node node;
105///
106/// return sizeof(node.d_next) + bsl::strlen(string) + 1;
107/// }
108/// };
109/// @endcode
110/// Then, the externally-supplied library defines the function that will create
111/// the linked list of nodes from a null-terminated array of pointers to
112/// C-strings:
113/// @code
114/// void externalPopulateStringList(Node **head,
115/// const char **stringArray,
116/// bslma::Allocator *allocator)
117/// // Create a linked list of strings beginning with the specified '*head'
118/// // containing the null-terminated strings from the null-terminated
119/// // 'stringArray'. Use the specified 'allocator' to supply memory.
120/// {
121/// *head = 0;
122/// const char *string;
123/// for (int ii = 0; 0 != (string = stringArray[ii]); ++ii) {
124/// Node *newNode = static_cast<Node *>(allocator->allocate(
125/// Node::sizeNeededForString(string)));
126/// assert(newNode != 0);
127///
128/// bsl::strcpy(newNode->d_string, string);
129///
130/// newNode->d_next = *head;
131/// *head = newNode;
132/// }
133/// }
134/// @endcode
135/// Next, our example function will begin with the externally-supplied buffered
136/// sequential allocator that we are to use:
137/// @code
138/// void printFromNodes(bsl::ostream *out) {
139/// enum { k_BUFFER_SIZE = 4 * 1024 };
140/// char buffer4k[k_BUFFER_SIZE];
141/// bdlma::BufferedSequentialAllocator bsAlloc(buffer4k, k_BUFFER_SIZE);
142/// @endcode
143/// There is a problem here, in that the nodes must be aligned by
144/// `sizeof(Node *)`, but our buffered sequential allocator, like most BDE
145/// allocators, has a "natural alignment" strategy (see @ref bsls_alignment ),
146/// meaning that it infers the required alignment from the size of the
147/// allocation requested. This would normally give us properly aligned memory
148/// if we were allocating by `sizeof(Node)`, but our `Node` objects are variable
149/// length, which will mislead the allocator to sometimes align the new segments
150/// by less than `sizeof(Node *)`.
151///
152/// Then, we solve this problem by using an aligning allocator to wrap the
153/// buffered sequential allocator, ensuring that the memory will still come from
154/// the buffered sequential allocator, but nonetheless be aligned to the
155/// alignment requirement of `Node`.
156/// @code
157/// enum { k_ALIGNMENT = bsls::AlignmentFromType<Node>::value };
158/// bdlma::AligningAllocator aligningAllocator(k_ALIGNMENT, &bsAlloc);
159/// @endcode
160/// Next, we define a null-terminated array of strings we would like to store in
161/// the list:
162/// @code
163/// const char *strings[] = {
164/// "A zinger is not a rebuttal.\n",
165/// "Humor is mankind's greatest blessing.\n",
166/// "As usual, the facts don't care about our feelings.\n",
167/// "Criticism is the only antidote to error.\n",
168/// "If you can't annoy somebody, there is little point in writing.\n",
169/// "Maybe all one can do is hope to end up with the right regrets.\n",
170/// "People may hear your words, but they feel your attitude.\n",
171/// "Imagination is a poor substitute for experience.\n",
172/// "We wanted a labor force, but human beings came.\n",
173/// "The reward of a thing well done is to have done it.\n",
174/// "Chance fights ever on the side of the prudent.\n",
175/// "The best time to make friends is before you need them.\n",
176/// 0 };
177/// @endcode
178/// Now, we call the function to put the strings into a linked list, passing it
179/// the aligning allocator:
180/// @code
181/// Node *head = 0;
182/// externalPopulateStringList(&head, strings, &aligningAllocator);
183/// @endcode
184/// Finally, we traverse the list and print out the strings, verifying that the
185/// nodes are properly aligned:
186/// @code
187/// for (const Node *node = head; node; node = node->d_next) {
188/// assert(0 == (reinterpret_cast<bsl::size_t>(node) &
189/// (k_ALIGNMENT - 1)));
190/// if (out) {
191/// *out << node->d_string;
192/// }
193/// }
194/// }
195/// @endcode
196/// @}
197/** @} */
198/** @} */
199
200/** @addtogroup bdl
201 * @{
202 */
203/** @addtogroup bdlma
204 * @{
205 */
206/** @addtogroup bdlma_aligningallocator
207 * @{
208 */
209
210#include <bdlscm_version.h>
211
212#include <bslma_allocator.h>
213
214#include <bsls_keyword.h>
215#include <bsls_types.h>
216
217#include <bsl_cstddef.h>
218
219
220namespace bdlma {
221
222 // =======================
223 // class AligningAllocator
224 // =======================
225
226/// This `class` provides a mechanism that serves as a wrapper around
227/// another allocator, passed at construction. The mechanism guarantees
228/// that all allocations passed to the underlying allocator will be aligned
229/// by the alignment specified at construction.
230///
231/// See @ref bdlma_aligningallocator
233
234 // DATA
235 bsls::Types::size_type d_mask; // alignment - 1
236
237 bslma::Allocator *d_allocator_p; // allocator indicated at
238 // construction
239
240 private:
241 // NOT IMPLEMENTED
243 AligningAllocator& operator=(
245
246 public:
247 // CREATORS
248
249 /// Create an `AligningAllocator` object that guarantees alignment by
250 /// the specified `alignment` (in bytes) of memory allocated.
251 /// Optionally specify a `basicAllocator` used to supply memory. If
252 /// `basicAllocator` is 0 or not supplied, the currently installed
253 /// default allocator is used. The behavior is undefined unless
254 /// `alignment` is a power of 2, and the alignment strategy of the
255 /// alocator used to supply memory is `BSLS_MAXIMUM` or `BSLS_NATURAL`.
257 bslma::Allocator *basicAllocator = 0);
258
259 // MANIPULATORS
260
261 /// Return a newly allocated block of memory of (at least) the specified
262 /// positive `size` (in bytes). If `size` is 0, a null pointer is
263 /// returned with no other effect. If this allocator cannot return the
264 /// requested number of bytes, then it will throw a `std::bad_alloc`
265 /// exception in an exception-enabled build, or else will abort the
266 /// program in a non-exception build. Note that the alignment of the
267 /// address returned conforms to the platform requirement for any object
268 /// of size `size` and is also guaranteed to be at least the alignment
269 /// passed to the constructor.
271
272 /// Return the memory block at the specified `address` back to this
273 /// allocator. If `address` is 0, this function has no effect. The
274 /// behavior is undefined unless `address` was allocated using this
275 /// allocator object and has not already been deallocated.
277};
278
279} // close package namespace
280
281
282#endif
283
284// ----------------------------------------------------------------------------
285// Copyright 2016 Bloomberg Finance L.P.
286//
287// Licensed under the Apache License, Version 2.0 (the "License");
288// you may not use this file except in compliance with the License.
289// You may obtain a copy of the License at
290//
291// http://www.apache.org/licenses/LICENSE-2.0
292//
293// Unless required by applicable law or agreed to in writing, software
294// distributed under the License is distributed on an "AS IS" BASIS,
295// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
296// See the License for the specific language governing permissions and
297// limitations under the License.
298// ----------------------------- END-OF-FILE ----------------------------------
299
300/** @} */
301/** @} */
302/** @} */
Definition bdlma_aligningallocator.h:232
AligningAllocator(bsls::Types::size_type alignment, bslma::Allocator *basicAllocator=0)
void deallocate(void *address) BSLS_KEYWORD_OVERRIDE
void * allocate(bsls::Types::size_type size) BSLS_KEYWORD_OVERRIDE
Definition bslma_allocator.h:457
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
#define BSLS_KEYWORD_DELETED
Definition bsls_keyword.h:609
#define BSLS_KEYWORD_OVERRIDE
Definition bsls_keyword.h:653
Definition bdlma_alignedallocator.h:276
std::size_t size_type
Definition bsls_types.h:124