BDE 4.39.x Production Release
Loading...
Searching...
No Matches
bdlma_alignedallocator.h
Go to the documentation of this file.
1/// @file bdlma_alignedallocator.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bdlma_alignedallocator.h -*-C++-*-
8#ifndef INCLUDED_BDLMA_ALIGNEDALLOCATOR
9#define INCLUDED_BDLMA_ALIGNEDALLOCATOR
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id$")
13
14/// @defgroup bdlma_alignedallocator bdlma_alignedallocator
15/// @brief Provide a protocol for memory allocators that support alignment.
16/// @addtogroup bdl
17/// @{
18/// @addtogroup bdlma
19/// @{
20/// @addtogroup bdlma_alignedallocator
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bdlma_alignedallocator-purpose"> Purpose</a>
25/// * <a href="#bdlma_alignedallocator-classes"> Classes </a>
26/// * <a href="#bdlma_alignedallocator-description"> Description </a>
27/// * <a href="#bdlma_alignedallocator-usage"> Usage </a>
28/// * <a href="#bdlma_alignedallocator-example-1-implementing-bdlma-alignedallocator"> Example 1: Implementing bdlma::AlignedAllocator </a>
29/// * <a href="#bdlma_alignedallocator-example-2-using-the-bdlma-alignedallocator-protocol"> Example 2: Using the bdlma::AlignedAllocator Protocol </a>
30///
31/// # Purpose {#bdlma_alignedallocator-purpose}
32/// Provide a protocol for memory allocators that support alignment.
33///
34/// # Classes {#bdlma_alignedallocator-classes}
35///
36/// - bdlma::AlignedAllocator: protocol for aligned memory allocators
37///
38/// @see bslma_allocator
39///
40/// # Description {#bdlma_alignedallocator-description}
41/// This component provides an implementation,
42/// `bdlma::AlignedAllocator`, of the base-level protocol (pure abstract
43/// interface) class, `bslma::Allocator`, providing the ability to allocate raw
44/// memory with a specified alignment. The following inheritance diagram shows
45/// the classes involved and their methods:
46/// @code
47/// ,----------------------.
48/// ( bdlma::AlignedAllocator )
49/// `----------------------'
50/// | allocateAligned
51/// V
52/// ,----------------.
53/// ( bslma::Allocator )
54/// `----------------'
55/// allocate
56/// deallocate
57/// @endcode
58/// The `allocateAligned` method supplies the address of a contiguous block of
59/// allocated memory of at least the indicated size, that is aligned to a given
60/// boundary. Note that this behavior is similar to the behavior of the POSIX
61/// function @ref posix_memalign .
62///
63/// ## Usage {#bdlma_alignedallocator-usage}
64///
65///
66/// This section illustrates intended use of this component.
67///
68/// ### Example 1: Implementing bdlma::AlignedAllocator {#bdlma_alignedallocator-example-1-implementing-bdlma-alignedallocator}
69///
70///
71/// The `bdlma::AlignedAllocator` protocol provided in this component defines a
72/// bilateral contract between suppliers and consumers of raw aligned memory.
73/// In order for the `bdlma::AlignedAllocator` interface to be useful, we must
74/// supply a concrete allocator that implements it.
75///
76/// In this example, we demonstrate how to adapt @ref posix_memalign on Linux and
77/// AIX, `memalign` on Solaris and `_aligned_malloc` on Windows, to this
78/// protocol base class:
79///
80/// First, we specify the interface of the concrete implementation of
81/// 'MyAlignedAllocator:
82/// @code
83/// // myposixmemalignallocator.h
84/// // ...
85///
86/// /// This class is a sample concrete implementation of the
87/// /// `bdlma::AlignedAllocator` protocol that provides direct access to
88/// /// the system-supplied `posix_memalign` and `free` on Linux and AIX
89/// /// platforms, `memalign` and `free` on Solaris, or `_aligned_malloc` and
90/// /// `_aligned_free` on Windows.
91/// class MyAlignedAllocator: public bdlma::AlignedAllocator {
92///
93/// private:
94/// // NOT IMPLEMENTED
95/// MyAlignedAllocator(const MyAlignedAllocator&);
96/// MyAlignedAllocator& operator=(const MyAlignedAllocator&);
97///
98/// public:
99/// // CREATORS
100///
101/// /// Create a `MyAlignedAllocator` object. Note that all objects of
102/// /// this class share the same underlying resource.
103/// MyAlignedAllocator();
104///
105/// /// Destroy this object. Note that destroying this object has no
106/// /// effect on any outstanding allocated memory.
107/// virtual ~MyAlignedAllocator();
108///
109/// // MANIPULATORS
110///
111/// /// Return a newly allocated block of memory of (at least) the
112/// /// specified positive `size` (in bytes). If `size` is 0, a null
113/// /// pointer is returned with no other effect. If this allocator
114/// /// cannot return the requested number of bytes, then it will throw
115/// /// an `std::bad_alloc` exception in an exception-enabled build, or
116/// /// else it will abort the program in a non-exception build. The
117/// /// behavior is undefined unless `0 <= size`. Note that the
118/// /// alignment of the address returned conforms to the platform
119/// /// requirement for any object of the `size`. Also note that global
120/// /// `operator new` is *not* called when `size` is 0 (in order to
121/// /// avoid having to acquire a lock, and potential contention in
122/// /// multi-threaded programs).
123/// virtual void *allocate(bsls::Types::size_type size);
124///
125/// /// Return the address of a newly allocated block of memory of at
126/// /// least the specified positive `size` (in bytes), sufficiently
127/// /// aligned such that the returned `address` satisfies, for the
128/// /// specified `alignment`, `0 == (address & (alignment - 1))`. If
129/// /// `size` is 0, a null pointer is returned with no other effect.
130/// /// If the requested number of appropriately aligned bytes cannot be
131/// /// returned, then a `bsl::bad_alloc` exception is thrown, or in a
132/// /// non-exception build the program is terminated. The behavior is
133/// /// undefined unless `alignment` is both a multiple of
134/// /// `sizeof(void *)` and an integral non-negative power of two.
135/// virtual void *allocateAligned(bsls::Types::size_type size,
136/// bsls::Types::size_type alignment);
137///
138/// /// Return the memory block at the specified `address` back to this
139/// /// allocator. If `address` is 0, this function has no effect. The
140/// /// behavior is undefined unless `address` was allocated using this
141/// /// allocator object and has not already been deallocated.
142/// virtual void deallocate(void *address);
143/// };
144/// // ...
145/// @endcode
146/// Then, we implement the creators, trivially, as this class contains no
147/// instance data members.
148/// @code
149/// // CREATORS
150/// MyAlignedAllocator::MyAlignedAllocator()
151/// {
152/// }
153///
154/// MyAlignedAllocator::~MyAlignedAllocator()
155/// {
156/// }
157/// @endcode
158/// Now, we define the virtual methods of `MyAlignedAllocator`. Note that these
159/// definitions are not `inline`, as they would not be inlined when invoked from
160/// the base class (the typical usage in this case):
161/// @code
162/// // MANIPULATORS
163/// void *MyAlignedAllocator::allocate(bsls::Types::size_type size)
164/// {
165/// if (0 == size) {
166/// return 0; // RETURN
167/// }
168///
169/// int alignment = bsls::AlignmentUtil::calculateAlignmentFromSize(size);
170/// return allocateAligned(size, alignment);
171/// }
172///
173/// void *MyAlignedAllocator::allocateAligned(bsls::Types::size_type size,
174/// bsls::Types::size_type alignment)
175/// {
176/// BSLS_ASSERT_SAFE(0 == (alignment & (alignment - 1)));
177/// BSLS_ASSERT_SAFE(0 == (alignment % sizeof(void *)));
178///
179/// if (0 == size) {
180/// return 0; // RETURN
181/// }
182///
183/// void *ret = 0;
184///
185/// #if defined(BSLS_PLATFORM_OS_WINDOWS)
186/// errno = 0;
187/// ret = _aligned_malloc(size, alignment);
188/// if (0 != errno) {
189/// bsls::BslExceptionUtil::throwBadAlloc();
190/// }
191/// #elif defined(BSLS_PLATFORM_OS_SOLARIS)
192/// ret = memalign(alignment, size);
193/// if (0 == ret) {
194/// bsls::BslExceptionUtil::throwBadAlloc();
195/// }
196/// #else
197/// int rc = ::posix_memalign(&ret, alignment, size);
198/// if (0 != rc) {
199/// bsls::BslExceptionUtil::throwBadAlloc();
200/// }
201/// #endif
202///
203/// return ret;
204/// }
205///
206/// void MyAlignedAllocator::deallocate(void *address)
207/// {
208/// if (0 == address) {
209/// return; // RETURN
210/// }
211/// #ifdef BSLS_PLATFORM_WINDOWS
212/// _aligned_free(address);
213/// #else
214/// ::free(address);
215/// #endif
216/// }
217/// @endcode
218/// Finally, we define a function `f` that instantiates an object of type
219/// `MyAlignedAllocator`:
220/// @code
221/// void f() {
222/// MyAlignedAllocator a;
223/// }
224/// @endcode
225/// Note that the memory is not released when the allocator goes out of scope.
226///
227/// ### Example 2: Using the bdlma::AlignedAllocator Protocol {#bdlma_alignedallocator-example-2-using-the-bdlma-alignedallocator-protocol}
228///
229///
230/// In this example we illustrate how to use the `bdlma::AlignedAllocator`
231/// protocol to allocate memory that is aligned to the beginning of a memory
232/// page. Third party libraries, for example device drivers that perform DMA
233/// access of device drivers, or some extreme optimizations to reduce the number
234/// of page faults, might require page aligned allocations.
235///
236/// First, we create an aligned allocator `myAlignedAllocator` using the class
237/// `MyAlignedAllocator` defined in the previous example, and obtain a
238/// `bdlma::AlignedAllocator` pointer to it:
239/// @code
240/// MyAlignedAllocator myAlignedAllocator;
241/// bdlma::AlignedAllocator *alignedAllocator = &myAlignedAllocator;
242/// @endcode
243/// Now, assuming a page size of 4K, we allocate a buffer of 1024 bytes of
244/// memory and indicate that it should be aligned on a 4096 boundary:
245/// @code
246/// char *address = (char *) alignedAllocator->allocateAligned(1024, 4096);
247/// @endcode
248/// Finally, we verify that the obtained address actually is aligned as
249/// expected:
250/// @code
251/// assert(0 == ((bsl::size_t)address & (4096 - 1)));
252/// @endcode
253/// @}
254/** @} */
255/** @} */
256
257/** @addtogroup bdl
258 * @{
259 */
260/** @addtogroup bdlma
261 * @{
262 */
263/** @addtogroup bdlma_alignedallocator
264 * @{
265 */
266
267#include <bslscm_version.h>
268
269#include <bslma_allocator.h>
270
271#include <bsls_annotation.h>
272#include <bsls_platform.h>
273#include <bsls_types.h>
274
275#include <bsl_cstddef.h>
276
277
278namespace bdlma {
279
280 // ======================
281 // class AlignedAllocator
282 // ======================
283
284/// This protocol provides a pure abstract interface and contract for
285/// clients and suppliers of raw aligned memory. If the requested memory
286/// cannot be returned, the contract requires that an `std::bad_alloc`
287/// exception be thrown.
288///
289/// See @ref bdlma_alignedallocator
291
292 public:
293 // MANIPULATORS
294
295 /// Return the address of a newly allocated block of memory of at least
296 /// the specified positive `size` (in bytes), sufficiently aligned such
297 /// that the returned `address` satisfies, for the specified
298 /// `alignment`, `0 == (address & (alignment - 1))`. If `size` is 0, a
299 /// null pointer is returned with no other effect. If the requested
300 /// number of appropriately aligned bytes cannot be returned, then a
301 /// `bsl::bad_alloc` exception is thrown, or in a non-exception build the program is terminated.
302 ///
303 /// \pre The behavior is undefined unless
304 /// `alignment` is both a multiple of `sizeof(void *)` and an integral
305 /// non-negative power of two.
307 bsls::Types::size_type alignment) = 0;
308};
309
310} // close package namespace
311
312
313#endif
314
315// ----------------------------------------------------------------------------
316// Copyright 2016 Bloomberg Finance L.P.
317//
318// Licensed under the Apache License, Version 2.0 (the "License");
319// you may not use this file except in compliance with the License.
320// You may obtain a copy of the License at
321//
322// http://www.apache.org/licenses/LICENSE-2.0
323//
324// Unless required by applicable law or agreed to in writing, software
325// distributed under the License is distributed on an "AS IS" BASIS,
326// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
327// See the License for the specific language governing permissions and
328// limitations under the License.
329// ----------------------------- END-OF-FILE ----------------------------------
330
331/** @} */
332/** @} */
333/** @} */
Definition bdlma_alignedallocator.h:290
virtual void * allocateAligned(bsls::Types::size_type size, bsls::Types::size_type alignment)=0
Definition bslma_allocator.h:545
#define BSLS_IDENT(str)
BSLS_IDENT() - insert string into .comment binary segment (if supported)
Definition bsls_ident.h:238
Definition bdlma_alignedallocator.h:278
std::size_t size_type
Definition bsls_types.h:126