BDE 4.39.x Production Release
Loading...
Searching...
No Matches
bsls_alignmentimp.h
Go to the documentation of this file.
1/// @file bsls_alignmentimp.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bsls_alignmentimp.h -*-C++-*-
8#ifndef INCLUDED_BSLS_ALIGNMENTIMP
9#define INCLUDED_BSLS_ALIGNMENTIMP
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bsls_alignmentimp bsls_alignmentimp
15/// @brief Provide implementation meta-functions for alignment computation.
16/// @addtogroup bsl
17/// @{
18/// @addtogroup bsls
19/// @{
20/// @addtogroup bsls_alignmentimp
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bsls_alignmentimp-purpose"> Purpose</a>
25/// * <a href="#bsls_alignmentimp-classes"> Classes </a>
26/// * <a href="#bsls_alignmentimp-description"> Description </a>
27/// * <a href="#bsls_alignmentimp-computing-alignment-for-a-type"> Computing Alignment for a Type </a>
28/// * <a href="#bsls_alignmentimp-computing-a-type-requiring-an-alignment"> Computing a Type Requiring an Alignment </a>
29/// * <a href="#bsls_alignmentimp-usage"> Usage </a>
30/// * <a href="#bsls_alignmentimp-example-1-alignmentimpcalc-template"> Example 1: AlignmentImpCalc Template </a>
31/// * <a href="#bsls_alignmentimp-example-2-types-supporting-alignmenttotype"> Example 2: Types Supporting AlignmentToType </a>
32///
33/// # Purpose {#bsls_alignmentimp-purpose}
34/// Provide implementation meta-functions for alignment computation.
35///
36/// # Classes {#bsls_alignmentimp-classes}
37///
38/// - bsls::AlignmentImpCalc: `TYPE` parameter to alignment `VALUE` map
39/// - bsls::AlignmentImpMatch: namespace for overloaded `match` functions
40/// - bsls::AlignmentImpPriorityToType: `PRIORITY` param to primitive type map
41/// - bsls::AlignmentImpTag: unique type of size `SIZE` (parameter)
42///
43/// @see bsls_alignmentfromtype, bsls_alignmenttotype, bsls_alignmentutil
44///
45/// # Description {#bsls_alignmentimp-description}
46/// This component provides a suite of template meta-functions that
47/// can be used to compute (at compile-time) various platform-dependent
48/// alignment information. The clients of this component are expected to be
49/// `bsls` components such as @ref bsls_alignmentfromtype , @ref bsls_alignmenttotype ,
50/// and @ref bsls_alignmentutil . Other client code should use one of these `bsls`
51/// components instead of using this component directly.
52///
53/// ## Computing Alignment for a Type {#bsls_alignmentimp-computing-alignment-for-a-type}
54///
55///
56/// The compiler alignment for a given type, `T`, can be computed by creating a
57/// structure containing a single `char` member followed by a `T` member:
58/// @code
59/// struct X {
60/// char d_c;
61/// T d_t;
62/// };
63/// @endcode
64/// The compiler lays this structure out in memory as follows:
65/// @code
66/// +---+---+-------+
67/// |d_c| P | d_t |
68/// +---+---+-------+
69/// @endcode
70/// where `P` is padding added by the compiler to ensure that `d_t` is properly
71/// aligned. The alignment for `T` is the number of bytes from the start of the
72/// structure to the beginning of `d_t`, which is also the total size of the
73/// structure minus the size of `d_t`:
74/// @code
75/// bsls::AlignmentImpCalc<T>::value == sizeof(X) - sizeof(T);
76/// @endcode
77/// Since `sizeof` yields a compile-time constant, the alignment can be computed
78/// at compile time.
79///
80/// ## Computing a Type Requiring an Alignment {#bsls_alignmentimp-computing-a-type-requiring-an-alignment}
81///
82///
83/// A considerably more difficult compile-time computation supported by this
84/// component is that of determining a fundamental type with the same alignment
85/// requirements of a given type `T`. This involves computing the alignment for
86/// `T`, as above, and then performing an alignment-to-type lookup, all at
87/// compile time. The general principles of this computation follow.
88///
89/// We would like to create a template class that is specialized for each
90/// fundamental type's alignment. Unfortunately, multiple types will have the
91/// same alignment and the compiler would issue a diagnostic if the same
92/// specialization was defined more than once. To disambiguate, we create a
93/// "priority" class for each fundamental type that arbitrarily ranks that type
94/// relative to all of the other fundamental types. Each priority class is
95/// derived from the next-lower priority class. A set of overloaded functions
96/// are created such that, given two fundamental types with the same alignment,
97/// overload resolution will pick the one with the highest priority (i.e., the
98/// most-derived priority type). The `sizeof` operator and several template
99/// specializations are used to determine the compiler's choice of overloaded
100/// `match` function. The return value is mapped to a priority, which is, in
101/// turn, mapped to an appropriate primitive type.
102///
103/// ## Usage {#bsls_alignmentimp-usage}
104///
105///
106/// This section illustrates the intended use of this component.
107///
108/// ### Example 1: AlignmentImpCalc Template {#bsls_alignmentimp-example-1-alignmentimpcalc-template}
109///
110///
111/// Suppose that we want to write a program that needs to calculate the
112/// alignment requirements of both user-defined types and built-in types.
113/// Further suppose that the program will run on a platform where the alignment
114/// requirement of `int` is 4 bytes.
115///
116/// First, we define a `struct`, `MyStruct`, for which want to determine the
117/// alignment requirement:
118/// @code
119/// struct MyStruct {
120/// char d_c;
121/// int d_i;
122/// short d_s;
123/// };
124/// @endcode
125/// Note that `int` is the most alignment-demanding type within `MyStruct`.
126///
127/// Now, we use `AlignmentImpCalc` to calculate the alignments of two
128/// types, `short` and the `MyStruct` we just defined:
129/// @code
130/// enum {
131/// SHORT_ALIGNMENT = bsls::AlignmentImpCalc<short >::value,
132/// MY_STRUCT_ALIGNMENT = bsls::AlignmentImpCalc<MyStruct>::value };
133/// @endcode
134/// Finally, we observe the values of our alignments, we observe that
135/// the size of the 2 objects is a multiple of each object's alignment
136/// (which is true for all C++ types), and we observe that the size of
137/// `MyStruct` is greater than its alignment.
138/// @code
139/// assert(2 == SHORT_ALIGNMENT);
140/// assert(4 == MY_STRUCT_ALIGNMENT);
141///
142/// assert(0 == sizeof(short ) % SHORT_ALIGNMENT);
143/// assert(0 == sizeof(MyStruct) % MY_STRUCT_ALIGNMENT);
144///
145/// assert(sizeof(MyStruct) > MY_STRUCT_ALIGNMENT);
146/// @endcode
147///
148/// ### Example 2: Types Supporting AlignmentToType {#bsls_alignmentimp-example-2-types-supporting-alignmenttotype}
149///
150///
151/// Suppose we to be able to determine a fundamental or pointer type that has
152/// both its size and alignment requirement equal to the alignment requirement
153/// of a specified template parameter type. We can use the `AlignmentImpTag`
154/// `struct` template, the overloads of `AlignmentImpMatch::match` class method,
155/// the `AiignmentImp_Priority` template class, and the
156/// `AlignmentImpPrioriityToType` template class to do this calculation.
157///
158/// First, we define a class template, `ConvertAlignmentToType`, that provides a
159/// `Type` alias to a fundamental or pointer type that has both its alignment
160/// requirement and size equal to the compile-time constant `ALIGNMENT` `int`
161/// parameter of the template.
162/// @code
163/// template <int ALIGNMENT>
164/// struct ConvertAlignmentToType {
165/// // This 'struct' provides a 'typedef', 'Type', that aliases a primitive
166/// // type having the specified 'ALIGNMENT' requirement and size.
167///
168/// private:
169/// // PRIVATE TYPES
170/// typedef typename bsls::AlignmentImpMatch::MaxPriority MaxPriority;
171/// // 'MaxPriority' is a typedef to the 'AlignmentImp_Priority'
172/// // template class having the highest permissible priority value.
173///
174/// typedef bsls::AlignmentImpTag<ALIGNMENT> Tag;
175/// // 'Tag' provides a typedef to the 'AlignmentImpTag' class
176/// // configured with this 'struct's 'ALIGNMENT' parameter.
177///
178/// enum {
179/// // Compute the priority of the primitive type corresponding to the
180/// // specified 'ALIGNMENT'. Many 'match' functions are declared, and
181/// // at least one whose alignment and size fields are identical and
182/// // equal to 'ALIGNMENT'. Of those who match, the first match will
183/// // be the one with the highest priority 'AlignmentImp_Priority'
184/// // arg.
185///
186/// PRIORITY = sizeof(bsls::AlignmentImpMatch::match(Tag(),
187/// Tag(),
188/// MaxPriority()))
189/// };
190///
191/// public:
192/// // TYPES
193/// typedef typename bsls::AlignmentImpPriorityToType<PRIORITY>::Type Type;
194/// // Convert the 'PRIORITY' value we calculated back to a type that
195/// // has the value 'ALIGNMENT' for both its alignment and it's size.
196/// };
197/// @endcode
198/// Then, we define two user defined types on which we will use
199/// `ConvertAlignmentToType` on:
200/// @code
201/// struct MyStructA {
202/// short d_s;
203/// double d_d;
204/// int d_i;
205/// };
206///
207/// struct MyStructB {
208/// double d_d[20];
209/// };
210/// @endcode
211/// Here, we calculate alignments for our 3 types with `AlignmentImpCalc`.
212/// @code
213/// const int INT_ALIGNMENT = bsls::AlignmentImpCalc<int >::value;
214/// const int A_ALIGNMENT = bsls::AlignmentImpCalc<MyStructA>::value;
215/// const int B_ALIGNMENT = bsls::AlignmentImpCalc<MyStructB>::value;
216/// @endcode
217/// Now, for each alignment requirement we just calculated, we utilize
218/// `ConvertAlignmentToType` to determine the fundamental or pointer
219/// type having both size and alignment requirement equal to the
220/// calculated alignment requirement:
221/// @code
222/// typedef ConvertAlignmentToType<INT_ALIGNMENT>::Type IntAlignType;
223/// typedef ConvertAlignmentToType<A_ALIGNMENT >::Type ThisAlignType;
224/// typedef ConvertAlignmentToType<B_ALIGNMENT >::Type ThatAlignType;
225/// @endcode
226/// Finally, we observe that the alignments of the `*AlignType`s are the
227/// same as the alignments of the types from which they are derived, and that
228/// all the type determined by `ConvertAlignmentToType` have sizes
229/// equal to their alignment requirements:
230/// @code
231/// assert(INT_ALIGNMENT == bsls::AlignmentImpCalc<IntAlignType >::value);
232/// assert(A_ALIGNMENT == bsls::AlignmentImpCalc<ThisAlignType>::value);
233/// assert(B_ALIGNMENT == bsls::AlignmentImpCalc<ThatAlignType>::value);
234///
235/// assert(INT_ALIGNMENT == sizeof(IntAlignType));
236/// assert(A_ALIGNMENT == sizeof(ThisAlignType));
237/// assert(B_ALIGNMENT == sizeof(ThatAlignType));
238/// @endcode
239/// @}
240/** @} */
241/** @} */
242
243/** @addtogroup bsl
244 * @{
245 */
246/** @addtogroup bsls
247 * @{
248 */
249/** @addtogroup bsls_alignmentimp
250 * @{
251 */
252
253#include <bsls_platform.h>
254
255
256
257namespace bsls {
258
259 // ======================
260 // struct AlignmentImpTag
261 // ======================
262
263/// This `struct` defines a unique type having the specified compile-time
264/// `SIZE`.
265///
266/// See @ref bsls_alignmentimp
267template <int SIZE>
269
270 // DATA
271 char d_dummy[SIZE];
272};
273
274 // =======================
275 // struct AlignmentImpCalc
276 // =======================
277
278/// This `struct` provides an enumerator `VALUE` that is initialized to the
279/// required alignment for the specified `TYPE`.
280///
281/// See @ref bsls_alignmentimp
282template <class TYPE>
284
285 private:
286 // PRIVATE TYPES
287
288 /// This private `struct` computes the required alignment for `TYPE`.
289 /// The compiler inserts sufficient padding after the `char` member so
290 /// that `d_aligned` is correctly aligned for `TYPE`. The distance from
291 /// the start of the structure to `d_aligned` is the alignment of
292 /// `TYPE`, and is computed as follows:
293 /// @code
294 /// sizeof(AlignmentImpCalc<TYPE>::AlignmentCalc) - sizeof(TYPE)
295 /// @endcode
296 ///
297 /// See @ref bsls_alignmentimp
298 struct AlignmentCalc {
299
300 // DATA
301 char d_c;
302 TYPE d_aligned;
303
304 private:
305 // NOT IMPLEMENTED
306
307 /// Prevent the compiler from automatically generating
308 /// default & copy constructors and destructor, as this could cause
309 /// problems if `TYPE` has constructors / destructor that are
310 /// private or unimplemented.
311 AlignmentCalc();
312 AlignmentCalc(const AlignmentCalc&);
313 ~AlignmentCalc();
314 };
315
316 public:
317 // TYPES
318 enum {
319 // Define the compile-time computed alignment value for 'TYPE'.
320
321 VALUE = sizeof(AlignmentCalc) - sizeof(TYPE)
322 };
323
324 /// Alias for the unique type for each alignment value.
326};
327
328#if defined(BSLS_PLATFORM_CPU_POWERPC) && defined(BSLS_PLATFORM_OS_LINUX)
329template <>
330struct AlignmentImpCalc <long double> {
331 // This 'struct' provides an enumerator 'VALUE' that is initialized to the
332 // required alignment for long double on Linux on POWER. This template
333 // specialization is for long double on Linux on POWER where default malloc
334 // in glibc returns memory aligned to 8-bytes, not 16-bytes. 8-byte
335 // alignment is sufficient for proper long double operation on POWER even
336 // though 16-byte alignment is more optimal (and is required for vector
337 // instructions).
338 //
339 // Note: the optional tcmalloc library returns memory aligned to 16-bytes.
340
341 public:
342 // TYPES
343 enum {
344 // Define the alignment value for long double on Linux on POWER.
345
346 VALUE = 8
347 };
348
349 typedef AlignmentImpTag<VALUE> Tag;
350 // Alias for the unique type for each alignment value.
351};
352#endif
353
354#if defined(BSLS_PLATFORM_CPU_X86) && !defined(BSLS_PLATFORM_CMP_MSVC)
355
356 // ===================================
357 // struct AlignmentImp8ByteAlignedType
358 // ===================================
359
360struct AlignmentImp8ByteAlignedType {
361 // On 32 bit x86, no natural type is aligned on an 8-byte boundary, but we
362 // need such a type to implement low-level constructs (e.g., 64-bit atomic
363 // types).
364
365 long long d_dummy __attribute__((__aligned__(8)));
366};
367
368 // ====================================
369 // struct AlignmentImp16ByteAlignedType
370 // ====================================
371
372struct AlignmentImp16ByteAlignedType {
373 // On 32 bit x86, no natural type is aligned on an 16-byte boundary, but we
374 // need such a type to implement low-level constructs (e.g., 128-bit atomic
375 // types).
376
377 long long d_dummy __attribute__((__aligned__(16)));
378};
379#endif
380
381 // =================================
382 // struct AlignmentImpPriorityToType
383 // =================================
384
385/// Specializations of this `struct` provide a primitive type (as a `Type`
386/// `typedef`) that corresponds to the specified `PRIORITY` level.
387///
388/// See @ref bsls_alignmentimp
389template <int PRIORITY>
392
393template <>
395 typedef long double Type;
396};
397
398template <>
400 typedef double Type;
401};
402
403template <>
405 typedef float Type;
406};
407
408template <>
410 typedef void (*Type)();
411};
412
413template <>
415 typedef void *Type;
416};
417
418template <>
420 typedef wchar_t Type;
421};
422
423template <>
425 typedef bool Type;
426};
427
428template <>
430 typedef long long Type;
431};
432
433template <>
435 typedef long Type;
436};
437
438template <>
440 typedef int Type;
441};
442
443template <>
445 typedef short Type;
446};
447
448template <>
450 typedef char Type;
451};
452
453#if defined(BSLS_PLATFORM_CPU_X86) && !defined(BSLS_PLATFORM_CMP_MSVC)
454template <>
456 typedef AlignmentImp8ByteAlignedType Type;
457};
458template <>
459struct AlignmentImpPriorityToType<14> {
460 typedef AlignmentImp16ByteAlignedType Type;
461};
462#endif
463
464 // ============================
465 // struct AlignmentImp_Priority
466 // ============================
467
468/// This `struct` provides a unique type that can be used as a trailing
469/// function parameter for overloaded functions having otherwise identical
470/// parameters. The highest-priority overloaded function can be selected by calling it with a high-priority argument.
471///
472/// \note Note that "highest priority"
473/// means the largest `VALUE` in this case.
474template <int VALUE>
477
478/// Specialization of `AlignmentImp_Priority` to terminate template
479/// instantiation.
480template <>
482};
483
484} // close package namespace
485
486namespace bsls {
487
488 // Declare a 'match' function that is overloaded based on the alignment and
489 // size of type 'T'. The function has no implementation since it is used
490 // only at compile-time to select the appropriate type for a given
491 // alignment. Return a tag that can used to look up a type using
492 // 'AlignmentImpPriorityToType<P>::Type'. Since multiple types can have
493 // the same alignment and size, duplicate definitions are avoided by
494 // overloading the function based on the priority 'P'. When used, the
495 // 'match' function with the highest priority is selected automatically.
496
497 // ========================
498 // struct AlignmentImpMatch
499 // ========================
500
501/// Namespace for a set of overloaded `match` functions, as defined by the
502/// macro `BSLS_ALIGNMENTIMP_MATCH_FUNC`.
503///
504/// See @ref bsls_alignmentimp
506
507# define BSLS_ALIGNMENTIMP_MATCH_FUNC(T, P) \
508 bsls::AlignmentImpTag<P> match( \
509 bsls::AlignmentImpCalc<T>::Tag, \
510 bsls::AlignmentImpTag<static_cast<int>(sizeof(T))>, \
511 bsls::AlignmentImp_Priority<P>)
512
513 // CLASS METHODS
514 static BSLS_ALIGNMENTIMP_MATCH_FUNC(long double, 1);
517 static BSLS_ALIGNMENTIMP_MATCH_FUNC(void (*)(), 4);
521 static BSLS_ALIGNMENTIMP_MATCH_FUNC(long long, 8);
526 // This function will match a type with the size and alignment the size
527 // of the type of the first macro argument, and return an object whose
528 // size is the 2nd argument of the macro.
529
530#if defined(BSLS_PLATFORM_CPU_X86) && !defined(BSLS_PLATFORM_CMP_MSVC)
531 static BSLS_ALIGNMENTIMP_MATCH_FUNC(AlignmentImp8ByteAlignedType, 13);
532 static BSLS_ALIGNMENTIMP_MATCH_FUNC(AlignmentImp16ByteAlignedType, 14);
533 // These types exist, and are needed, only on 32 bit x86 unixe
534
536#else
538#endif
539};
540
541} // close package namespace
542
543#undef BSLS_ALIGNMENTIMP_MATCH_FUNC
544
545
546
547#endif
548
549// ----------------------------------------------------------------------------
550// Copyright 2013 Bloomberg Finance L.P.
551//
552// Licensed under the Apache License, Version 2.0 (the "License");
553// you may not use this file except in compliance with the License.
554// You may obtain a copy of the License at
555//
556// http://www.apache.org/licenses/LICENSE-2.0
557//
558// Unless required by applicable law or agreed to in writing, software
559// distributed under the License is distributed on an "AS IS" BASIS,
560// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
561// See the License for the specific language governing permissions and
562// limitations under the License.
563// ----------------------------- END-OF-FILE ----------------------------------
564
565/** @} */
566/** @} */
567/** @} */
#define BSLS_ALIGNMENTIMP_MATCH_FUNC(T, P)
Definition bsls_alignmentimp.h:507
#define BSLS_IDENT(str)
BSLS_IDENT() - insert string into .comment binary segment (if supported)
Definition bsls_ident.h:238
Definition bdlt_iso8601util.h:707
Definition bsls_alignmentimp.h:283
AlignmentImpTag< VALUE > Tag
Alias for the unique type for each alignment value.
Definition bsls_alignmentimp.h:325
@ VALUE
Definition bsls_alignmentimp.h:321
Definition bsls_alignmentimp.h:505
AlignmentImp_Priority< 12 > MaxPriority
Definition bsls_alignmentimp.h:537
static BSLS_ALIGNMENTIMP_MATCH_FUNC(long long, 8)
static BSLS_ALIGNMENTIMP_MATCH_FUNC(int, 10)
static BSLS_ALIGNMENTIMP_MATCH_FUNC(wchar_t, 6)
static BSLS_ALIGNMENTIMP_MATCH_FUNC(float, 3)
static BSLS_ALIGNMENTIMP_MATCH_FUNC(long, 9)
static BSLS_ALIGNMENTIMP_MATCH_FUNC(long double, 1)
static BSLS_ALIGNMENTIMP_MATCH_FUNC(short, 11)
static BSLS_ALIGNMENTIMP_MATCH_FUNC(double, 2)
static BSLS_ALIGNMENTIMP_MATCH_FUNC(char, 12)
static BSLS_ALIGNMENTIMP_MATCH_FUNC(bool, 7)
static BSLS_ALIGNMENTIMP_MATCH_FUNC(void(*)(), 4)
static BSLS_ALIGNMENTIMP_MATCH_FUNC(void *, 5)
int Type
Definition bsls_alignmentimp.h:440
short Type
Definition bsls_alignmentimp.h:445
char Type
Definition bsls_alignmentimp.h:450
long double Type
Definition bsls_alignmentimp.h:395
double Type
Definition bsls_alignmentimp.h:400
float Type
Definition bsls_alignmentimp.h:405
void * Type
Definition bsls_alignmentimp.h:415
wchar_t Type
Definition bsls_alignmentimp.h:420
bool Type
Definition bsls_alignmentimp.h:425
long long Type
Definition bsls_alignmentimp.h:430
long Type
Definition bsls_alignmentimp.h:435
Definition bsls_alignmentimp.h:390
Definition bsls_alignmentimp.h:268
char d_dummy[SIZE]
Definition bsls_alignmentimp.h:271
Definition bsls_alignmentimp.h:475