BDE 4.39.x 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 ///
212 /// \note Note that to allow the union to access this typedef it must be
213 /// declared with public access.
215
216#if defined(BSLS_COMPILERFEATURES_SUPPORT_ALIGNAS)
217 // The C++11 implementation uses the 'alignas' keyword to ensure the
218 // alignment of 'd_buffer'.
219
220 alignas(ALIGNMENT) char d_buffer[SIZE];
221#else
222 // The C++03 implementation uses a union data member to ensure the
223 // alignment of 'd_buffer'.
224
225 char d_buffer[SIZE];
227#endif
228};
229
230#if defined(BSLS_PLATFORM_CMP_MSVC) && !defined(BSLS_COMPILERFEATURES_SUPPORT_ALIGNAS)
231// We provide template specializations for MSVC using __declspec(align).
232// Note that MSVC does not enforce the alignment of (at least) 'double'
233// variables on the stack. (internal issue 64140445).
234
235#define BSLS_ALIGNAS(N) __declspec(align(N))
236template <int SIZE>
237union AlignedBuffer_Data<SIZE, 1> {BSLS_ALIGNAS(1) char d_buffer[SIZE]; };
238template <int SIZE>
239union AlignedBuffer_Data<SIZE, 2> {BSLS_ALIGNAS(2) char d_buffer[SIZE]; };
240template <int SIZE>
241union AlignedBuffer_Data<SIZE, 4> {BSLS_ALIGNAS(4) char d_buffer[SIZE]; };
242template <int SIZE>
243union AlignedBuffer_Data<SIZE, 8> {BSLS_ALIGNAS(8) char d_buffer[SIZE]; };
244template <int SIZE>
245union AlignedBuffer_Data<SIZE, 16> {BSLS_ALIGNAS(16) char d_buffer[SIZE]; };
246#undef BSLS_ALIGNAS
247#endif // defined(BSLS_PLATFORM_CMP_MSVC)
248
249 // ===================
250 // class AlignedBuffer
251 // ===================
252
253/// An instance of this union is a block of raw memory of specified `SIZE`
254/// and `ALIGNMENT`. A `AlignedBuffer` object does not manage the
255/// construction or destruction of any other objects. `SIZE` is rounded up
256/// to the nearest multiple of `ALIGNMENT`. An instantiation of this union
257/// template will not compile unless `ALIGNMENT` is a power of two not
258/// larger than `AlignmentUtil::BSLS_MAX_ALIGNMENT`.
259///
260/// See @ref bsls_alignedbuffer
261template <int SIZE, int ALIGNMENT = AlignmentUtil::BSLS_MAX_ALIGNMENT>
263
264 // DATA
266
267 public:
268 // CREATORS Note that We deliberately omit defining constructors and
269 // destructors in order to keep this union "POD-like". In particular, a
270 // 'AlignedBuffer' may be used as a member in another 'union'. Copying a
271 // 'AlignedBuffer' assignment or copy construction will result in a
272 // bit-wise copy and will not invoke any user-defined assignment operators
273 // or copy constructors.
274
275 // MANIPULATORS
276
277 /// Return a the address of the first byte of this object, cast to a
278 /// `char*` pointer.
279 char *buffer();
280
281 // ACCESSORS
282
283 /// Return a the address of the first byte of this object, cast to a
284 /// `const char*` pointer.
285 const char *buffer() const;
286};
287
288// ============================================================================
289// INLINE FUNCTION DEFINITIONS
290// ============================================================================
291
292// MANIPULATORS
293template <int SIZE, int ALIGNMENT>
294inline
296{
297 return d_data.d_buffer;
298}
299
300// ACCESSORS
301template <int SIZE, int ALIGNMENT>
302inline
304{
305 return d_data.d_buffer;
306}
307
308} // close package namespace
309
310#ifndef BDE_OPENSOURCE_PUBLICATION // BACKWARD_COMPATIBILITY
311// ============================================================================
312// BACKWARD COMPATIBILITY
313// ============================================================================
314
315#ifdef bsls_AlignedBuffer
316#undef bsls_AlignedBuffer
317#endif
318/// This alias is defined for backward compatibility.
319#define bsls_AlignedBuffer bsls::AlignedBuffer
320#endif // BDE_OPENSOURCE_PUBLICATION -- BACKWARD_COMPATIBILITY
321
322
323
324#endif
325
326// ----------------------------------------------------------------------------
327// Copyright 2013 Bloomberg Finance L.P.
328//
329// Licensed under the Apache License, Version 2.0 (the "License");
330// you may not use this file except in compliance with the License.
331// You may obtain a copy of the License at
332//
333// http://www.apache.org/licenses/LICENSE-2.0
334//
335// Unless required by applicable law or agreed to in writing, software
336// distributed under the License is distributed on an "AS IS" BASIS,
337// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
338// See the License for the specific language governing permissions and
339// limitations under the License.
340// ----------------------------- END-OF-FILE ----------------------------------
341
342/** @} */
343/** @} */
344/** @} */
Definition bsls_alignedbuffer.h:262
char * buffer()
Definition bsls_alignedbuffer.h:295
const char * buffer() const
Definition bsls_alignedbuffer.h:303
#define BSLS_IDENT(str)
BSLS_IDENT() - insert string into .comment binary segment (if supported)
Definition bsls_ident.h:238
Definition bdlt_iso8601util.h:707
AlignmentImpPriorityToType< PRIORITY >::Type Type
Definition bsls_alignmenttotype.h:396
Definition bsls_alignedbuffer.h:206
AlignmentToType< ALIGNMENT >::Type AlignmentType
Definition bsls_alignedbuffer.h:214
AlignmentType d_align
Definition bsls_alignedbuffer.h:226
char d_buffer[SIZE]
Definition bsls_alignedbuffer.h:225