BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bsls_alignedbuffer.h
Go to the documentation of this file.
1/// @file bsls_alignedbuffer.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bsls_alignedbuffer.h -*-C++-*-
8#ifndef INCLUDED_BSLS_ALIGNEDBUFFER
9#define INCLUDED_BSLS_ALIGNEDBUFFER
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bsls_alignedbuffer bsls_alignedbuffer
15/// @brief Provide raw buffers with user-specified size and alignment.
16/// @addtogroup bsl
17/// @{
18/// @addtogroup bsls
19/// @{
20/// @addtogroup bsls_alignedbuffer
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bsls_alignedbuffer-purpose"> Purpose</a>
25/// * <a href="#bsls_alignedbuffer-classes"> Classes </a>
26/// * <a href="#bsls_alignedbuffer-description"> Description </a>
27/// * <a href="#bsls_alignedbuffer-single-object-buffers"> Single-Object Buffers </a>
28/// * <a href="#bsls_alignedbuffer-stack-alignment"> Stack Alignment </a>
29/// * <a href="#bsls_alignedbuffer-known-issues"> Known issues </a>
30/// * <a href="#bsls_alignedbuffer-usage"> Usage </a>
31///
32/// # Purpose {#bsls_alignedbuffer-purpose}
33/// Provide raw buffers with user-specified size and alignment.
34///
35/// # Classes {#bsls_alignedbuffer-classes}
36///
37/// - bsls::AlignedBuffer: Uninitialized buffer of specified size and alignment
38///
39/// @see bsls_objectbuffer, bsls_alignmenttotype
40///
41/// # Description {#bsls_alignedbuffer-description}
42/// This component provides a templated buffer type with a
43/// user-specified compile-time size and user-specified alignment. The user
44/// instantiates `bsls::AlignedBuffer` with specific size and alignment
45/// requirements, and then uses that memory as needed. If an alignment is not
46/// specified at template instantiation, then the buffer object is maximally
47/// aligned.
48///
49/// Typically, `bsls::AlignedBuffer` is used in situations where it is desirable
50/// to allocate a block of properly-aligned raw memory from somewhere other than
51/// the heap, e.g., on the stack or within an aggregate object, including within
52/// a union. It is a convenient way to create a small heap from which one or
53/// more objects are allocated at run-time.
54///
55/// ## Single-Object Buffers {#bsls_alignedbuffer-single-object-buffers}
56///
57///
58/// Although, for a given type `T`,
59/// `bsls::AlignedBuffer<sizeof(T), bsls::AlignmentFromType<T>::value>` will
60/// produce a buffer properly sized and aligned to hold a `T` object, it is
61/// simpler and clearer to use `bsls::ObjectBuffer<T>` for this purpose. See
62/// the @ref bsls_objectbuffer component for more information.
63///
64/// ## Stack Alignment {#bsls_alignedbuffer-stack-alignment}
65///
66///
67/// On platforms with 32-bit words, there is usually no efficiency gain by using
68/// more than 4-byte alignment. Yet some compilers use 8-byte alignment for
69/// `long long` or `double`, presumably so that the code will run faster on a
70/// future 64-bit CPU. The program loader, however, has no reason to presume
71/// more than 4-byte alignment when allocating the program stack. This can
72/// result in stack objects appearing to be misaligned relative to the
73/// alignments computed by this component. This is not a bug in either this
74/// component nor in the compiler, but it is somewhat surprising. We have seen
75/// this behavior on the MS VC++ 7 platform. See also the "Surprises and
76/// Anomalies" section in `bsls_alignmentfromtype.h`.
77///
78/// ## Known issues {#bsls_alignedbuffer-known-issues}
79///
80///
81/// On all versions of the Microsoft compiler prior to MSVC 14.0 (2015), passing
82/// `AlignedBuffer` or an object containing `AlignedBuffer` as a *by-value*
83/// function argument would lead to C2719 error (see
84/// https://msdn.microsoft.com/en-us/library/373ak2y1.aspx). In versions 14.10
85/// (2017) through 16.8 (2019) it can trigger a compiler bug leading to crashes
86/// due to the destructor being invoked with an incorrect `this` pointer. This
87/// bug has been observed only building for x86 (32-bit) platform in Debug mode
88/// (specifically with /Od /Ob0 flags), e.g.:
89/// @code
90/// struct X {
91/// bsls::AlignedBuffer<1, 8> d_buffer;
92/// };
93///
94/// void func(X) {}
95///
96/// int main()
97/// {
98/// func(X()); // The destructor of 'X' is called with broken 'this'.
99/// }
100/// @endcode
101/// See DRQS 151904020 for more details.
102///
103/// This was fixed my Microsoft in MSVC 2019 version 16.9, for details see:
104/// https://developercommunity.visualstudio.com/t/incorrect-code-gen-missing-error/831543
105///
106/// ## Usage {#bsls_alignedbuffer-usage}
107///
108///
109/// The `allocateFromBuffer` function below uses an aligned buffer as a small
110/// heap from which objects can be allocated. We choose `int` alignment (4-byte
111/// alignment) for our buffer because the objects we are allocating are composed
112/// of `char`, `short`, and `int` values only. If no alignment were specified,
113/// the buffer would be maximally aligned, which could be wasteful on some
114/// platforms.
115/// @code
116/// const int MY_ALIGNMENT = bsls::AlignmentFromType<int>::value;
117/// bsls::AlignedBuffer<1000, MY_ALIGNMENT> my_AllocBuffer;
118/// const char* my_AllocEnd = my_AllocBuffer.buffer() + 1000;
119/// char *my_AllocPtr = my_AllocBuffer.buffer();
120/// // Invariant: my_AllocPtr is always aligned on a multiple of 4 bytes
121///
122/// static void *allocateFromBuffer(int size)
123/// {
124/// if (size > my_AllocEnd - my_AllocPtr)
125/// return 0; // Out of buffer space
126///
127/// void *result = my_AllocPtr;
128/// my_AllocPtr += size;
129/// if (size % MY_ALIGNMENT) {
130/// // re-establish invariant by re-aligning my_AllocPtr
131/// my_AllocPtr += MY_ALIGNMENT - size % MY_ALIGNMENT;
132/// }
133///
134/// assert(0 == size_t(my_AllocPtr) % MY_ALIGNMENT); // Test invariant
135///
136/// return result;
137/// }
138/// @endcode
139/// Below, we use our allocation function to allocate arrays of `char`, `short`,
140/// and user-defined `Object` types from the static buffer. Note that our
141/// `Object` structure is composed of members that have alignment requirements
142/// less than or equal to `int`s alignment requirements.
143/// @code
144/// struct Object {
145/// char d_c;
146/// short d_s;
147/// int d_i;
148/// };
149///
150/// int main()
151/// {
152/// // Allocate three 'char's from the buffer.
153/// char *charPtr = (char *) allocateFromBuffer(3 * sizeof(char));
154/// assert(0 == size_t(charPtr) % MY_ALIGNMENT);
155///
156/// // Allocate three 'short's from the buffer.
157/// short *shortPtr = (short *) allocateFromBuffer(3 * sizeof(short));
158/// assert(0 == size_t(shortPtr) % MY_ALIGNMENT);
159///
160/// // Allocate three 'Object's from the buffer
161/// Object *objPtr = (Object *) allocateFromBuffer(3 * sizeof(Object));
162/// assert(0 == size_t(objPtr) % MY_ALIGNMENT);
163///
164/// if (!charPtr || !shortPtr || !objPtr) {
165/// fprintf(stderr, "Global buffer is not large enough.\n");
166/// return -1;
167/// }
168///
169/// // ...
170///
171/// return 0;
172/// }
173/// @endcode
174/// @}
175/** @} */
176/** @} */
177
178/** @addtogroup bsl
179 * @{
180 */
181/** @addtogroup bsls
182 * @{
183 */
184/** @addtogroup bsls_alignedbuffer
185 * @{
186 */
187
188#include <bsls_alignmenttotype.h>
189#include <bsls_alignmentutil.h>
191#include <bsls_platform.h>
192
193
194
195namespace bsls {
196
197 // ========================
198 // union AlignedBuffer_Data
199 // ========================
200
201/// This *private* implementation type provides a public `char` array
202/// data member `d_buffer` whose length is the specifed (template parameter)
203/// `SIZE` and which is aligned according to the specified (template
204/// parameter) `ALIGNMENT`.
205template <int SIZE, int ALIGNMENT>
207
208 public:
209 /// Define an alias for alignment type to work around a Sun CC 5.5 bug
210 /// that gives a warning if the type is directly accessed in the union.
211 /// Note that to allow the union to access this typedef it must be
212 /// declared with public access.
214
215#if defined(BSLS_COMPILERFEATURES_SUPPORT_ALIGNAS)
216 // The C++11 implementation uses the 'alignas' keyword to ensure the
217 // alignment of 'd_buffer'.
218
219 alignas(ALIGNMENT) char d_buffer[SIZE];
220#else
221 // The C++03 implementation uses a union data member to ensure the
222 // alignment of 'd_buffer'.
223
224 char d_buffer[SIZE];
226#endif
227};
228
229#if defined(BSLS_PLATFORM_CMP_MSVC) && !defined(BSLS_COMPILERFEATURES_SUPPORT_ALIGNAS)
230// We provide template specializations for MSVC using __declspec(align).
231// Note that MSVC does not enforce the alignment of (at least) 'double'
232// variables on the stack. (internal issue 64140445).
233
234#define BSLS_ALIGNAS(N) __declspec(align(N))
235template <int SIZE>
236union AlignedBuffer_Data<SIZE, 1> {BSLS_ALIGNAS(1) char d_buffer[SIZE]; };
237template <int SIZE>
238union AlignedBuffer_Data<SIZE, 2> {BSLS_ALIGNAS(2) char d_buffer[SIZE]; };
239template <int SIZE>
240union AlignedBuffer_Data<SIZE, 4> {BSLS_ALIGNAS(4) char d_buffer[SIZE]; };
241template <int SIZE>
242union AlignedBuffer_Data<SIZE, 8> {BSLS_ALIGNAS(8) char d_buffer[SIZE]; };
243template <int SIZE>
244union AlignedBuffer_Data<SIZE, 16> {BSLS_ALIGNAS(16) char d_buffer[SIZE]; };
245#undef BSLS_ALIGNAS
246#endif // defined(BSLS_PLATFORM_CMP_MSVC)
247
248 // ===================
249 // class AlignedBuffer
250 // ===================
251
252/// An instance of this union is a block of raw memory of specified `SIZE`
253/// and `ALIGNMENT`. A `AlignedBuffer` object does not manage the
254/// construction or destruction of any other objects. `SIZE` is rounded up
255/// to the nearest multiple of `ALIGNMENT`. An instantiation of this union
256/// template will not compile unless `ALIGNMENT` is a power of two not
257/// larger than `AlignmentUtil::BSLS_MAX_ALIGNMENT`.
258///
259/// See @ref bsls_alignedbuffer
260template <int SIZE, int ALIGNMENT = AlignmentUtil::BSLS_MAX_ALIGNMENT>
262
263 // DATA
265
266 public:
267 // CREATORS Note that We deliberately omit defining constructors and
268 // destructors in order to keep this union "POD-like". In particular, a
269 // 'AlignedBuffer' may be used as a member in another 'union'. Copying a
270 // 'AlignedBuffer' assignment or copy construction will result in a
271 // bit-wise copy and will not invoke any user-defined assignment operators
272 // or copy constructors.
273
274 // MANIPULATORS
275
276 /// Return a the address of the first byte of this object, cast to a
277 /// `char*` pointer.
278 char *buffer();
279
280 // ACCESSORS
281
282 /// Return a the address of the first byte of this object, cast to a
283 /// `const char*` pointer.
284 const char *buffer() const;
285};
286
287// ============================================================================
288// INLINE FUNCTION DEFINITIONS
289// ============================================================================
290
291// MANIPULATORS
292template <int SIZE, int ALIGNMENT>
293inline
295{
296 return d_data.d_buffer;
297}
298
299// ACCESSORS
300template <int SIZE, int ALIGNMENT>
301inline
303{
304 return d_data.d_buffer;
305}
306
307} // close package namespace
308
309#ifndef BDE_OPENSOURCE_PUBLICATION // BACKWARD_COMPATIBILITY
310// ============================================================================
311// BACKWARD COMPATIBILITY
312// ============================================================================
313
314#ifdef bsls_AlignedBuffer
315#undef bsls_AlignedBuffer
316#endif
317/// This alias is defined for backward compatibility.
318#define bsls_AlignedBuffer bsls::AlignedBuffer
319#endif // BDE_OPENSOURCE_PUBLICATION -- BACKWARD_COMPATIBILITY
320
321
322
323#endif
324
325// ----------------------------------------------------------------------------
326// Copyright 2013 Bloomberg Finance L.P.
327//
328// Licensed under the Apache License, Version 2.0 (the "License");
329// you may not use this file except in compliance with the License.
330// You may obtain a copy of the License at
331//
332// http://www.apache.org/licenses/LICENSE-2.0
333//
334// Unless required by applicable law or agreed to in writing, software
335// distributed under the License is distributed on an "AS IS" BASIS,
336// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
337// See the License for the specific language governing permissions and
338// limitations under the License.
339// ----------------------------- END-OF-FILE ----------------------------------
340
341/** @} */
342/** @} */
343/** @} */
Definition bsls_alignedbuffer.h:261
char * buffer()
Definition bsls_alignedbuffer.h:294
const char * buffer() const
Definition bsls_alignedbuffer.h:302
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
Definition bdlt_iso8601util.h:691
AlignmentImpPriorityToType< PRIORITY >::Type Type
Definition bsls_alignmenttotype.h:394
Definition bsls_alignedbuffer.h:206
AlignmentToType< ALIGNMENT >::Type AlignmentType
Definition bsls_alignedbuffer.h:213
AlignmentType d_align
Definition bsls_alignedbuffer.h:225
char d_buffer[SIZE]
Definition bsls_alignedbuffer.h:224