BDE 4.14.0 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`.
265template <int SIZE>
267
268 // DATA
269 char d_dummy[SIZE];
270};
271
272 // =======================
273 // struct AlignmentImpCalc
274 // =======================
275
276/// This `struct` provides an enumerator `VALUE` that is initialized to the
277/// required alignment for the specified `TYPE`.
278template <class TYPE>
280
281 private:
282 // PRIVATE TYPES
283
284 /// This private `struct` computes the required alignment for `TYPE`.
285 /// The compiler inserts sufficient padding after the `char` member so
286 /// that `d_aligned` is correctly aligned for `TYPE`. The distance from
287 /// the start of the structure to `d_aligned` is the alignment of
288 /// `TYPE`, and is computed as follows:
289 /// @code
290 /// sizeof(AlignmentImpCalc<TYPE>::AlignmentCalc) - sizeof(TYPE)
291 /// @endcode
292 struct AlignmentCalc {
293
294 // DATA
295 char d_c;
296 TYPE d_aligned;
297
298 private:
299 // NOT IMPLEMENTED
300
301 AlignmentCalc();
302 /// Prevent the compiler from automatically generating
303 /// default & copy constructors and destructor, as this could cause
304 /// problems if `TYPE` has constructors / destructor that are
305 /// private or unimplemented.
306 AlignmentCalc(const AlignmentCalc&);
307 ~AlignmentCalc();
308 };
309
310 public:
311 // TYPES
312 enum {
313 // Define the compile-time computed alignment value for 'TYPE'.
314
315 VALUE = sizeof(AlignmentCalc) - sizeof(TYPE)
316 };
317
318 /// Alias for the unique type for each alignment value.
320};
321
322#if defined(BSLS_PLATFORM_CPU_POWERPC) && defined(BSLS_PLATFORM_OS_LINUX)
323template <>
324struct AlignmentImpCalc <long double> {
325 // This 'struct' provides an enumerator 'VALUE' that is initialized to the
326 // required alignment for long double on Linux on POWER. This template
327 // specialization is for long double on Linux on POWER where default malloc
328 // in glibc returns memory aligned to 8-bytes, not 16-bytes. 8-byte
329 // alignment is sufficient for proper long double operation on POWER even
330 // though 16-byte alignment is more optimal (and is required for vector
331 // instructions).
332 //
333 // Note: the optional tcmalloc library returns memory aligned to 16-bytes.
334
335 public:
336 // TYPES
337 enum {
338 // Define the alignment value for long double on Linux on POWER.
339
340 VALUE = 8
341 };
342
343 typedef AlignmentImpTag<VALUE> Tag;
344 // Alias for the unique type for each alignment value.
345};
346#endif
347
348#if defined(BSLS_PLATFORM_CPU_X86) && !defined(BSLS_PLATFORM_CMP_MSVC)
349
350 // ===================================
351 // struct AlignmentImp8ByteAlignedType
352 // ===================================
353
354struct AlignmentImp8ByteAlignedType {
355 // On 32 bit x86, no natural type is aligned on an 8-byte boundary, but we
356 // need such a type to implement low-level constructs (e.g., 64-bit atomic
357 // types).
358
359 long long d_dummy __attribute__((__aligned__(8)));
360};
361
362 // ====================================
363 // struct AlignmentImp16ByteAlignedType
364 // ====================================
365
366struct AlignmentImp16ByteAlignedType {
367 // On 32 bit x86, no natural type is aligned on an 16-byte boundary, but we
368 // need such a type to implement low-level constructs (e.g., 128-bit atomic
369 // types).
370
371 long long d_dummy __attribute__((__aligned__(16)));
372};
373#endif
374
375 // =================================
376 // struct AlignmentImpPriorityToType
377 // =================================
378
379/// Specializations of this `struct` provide a primitive type (as a `Type`
380/// `typedef`) that corresponds to the specified `PRIORITY` level.
381template <int PRIORITY>
384
385template <>
387 typedef long double Type;
388};
389
390template <>
392 typedef double Type;
393};
394
395template <>
397 typedef float Type;
398};
399
400template <>
402 typedef void (*Type)();
403};
404
405template <>
407 typedef void *Type;
408};
409
410template <>
412 typedef wchar_t Type;
413};
414
415template <>
417 typedef bool Type;
418};
419
420template <>
422 typedef long long Type;
423};
424
425template <>
427 typedef long Type;
428};
429
430template <>
432 typedef int Type;
433};
434
435template <>
437 typedef short Type;
438};
439
440template <>
442 typedef char Type;
443};
444
445#if defined(BSLS_PLATFORM_CPU_X86) && !defined(BSLS_PLATFORM_CMP_MSVC)
446template <>
448 typedef AlignmentImp8ByteAlignedType Type;
449};
450template <>
451struct AlignmentImpPriorityToType<14> {
452 typedef AlignmentImp16ByteAlignedType Type;
453};
454#endif
455
456 // ============================
457 // struct AlignmentImp_Priority
458 // ============================
459
460/// This `struct` provides a unique type that can be used as a trailing
461/// function parameter for overloaded functions having otherwise identical
462/// parameters. The highest-priority overloaded function can be selected by
463/// calling it with a high-priority argument. Note that "highest priority"
464/// means the largest `VALUE` in this case.
465template <int VALUE>
468
469/// Specialization of `AlignmentImp_Priority` to terminate template
470/// instantiation.
471template <>
473};
474
475} // close package namespace
476
477namespace bsls {
478
479 // Declare a 'match' function that is overloaded based on the alignment and
480 // size of type 'T'. The function has no implementation since it is used
481 // only at compile-time to select the appropriate type for a given
482 // alignment. Return a tag that can used to look up a type using
483 // 'AlignmentImpPriorityToType<P>::Type'. Since multiple types can have
484 // the same alignment and size, duplicate definitions are avoided by
485 // overloading the function based on the priority 'P'. When used, the
486 // 'match' function with the highest priority is selected automatically.
487
488 // ========================
489 // struct AlignmentImpMatch
490 // ========================
491
492/// Namespace for a set of overloaded `match` functions, as defined by the
493/// macro `BSLS_ALIGNMENTIMP_MATCH_FUNC`.
495
496# define BSLS_ALIGNMENTIMP_MATCH_FUNC(T, P) \
497 bsls::AlignmentImpTag<P> match( \
498 bsls::AlignmentImpCalc<T>::Tag, \
499 bsls::AlignmentImpTag<static_cast<int>(sizeof(T))>, \
500 bsls::AlignmentImp_Priority<P>)
501
502 // CLASS METHODS
503 static BSLS_ALIGNMENTIMP_MATCH_FUNC(long double, 1);
506 static BSLS_ALIGNMENTIMP_MATCH_FUNC(void (*)(), 4);
510 static BSLS_ALIGNMENTIMP_MATCH_FUNC(long long, 8);
515 // This function will match a type with the size and alignment the size
516 // of the type of the first macro argument, and return an object whose
517 // size is the 2nd argument of the macro.
518
519#if defined(BSLS_PLATFORM_CPU_X86) && !defined(BSLS_PLATFORM_CMP_MSVC)
520 static BSLS_ALIGNMENTIMP_MATCH_FUNC(AlignmentImp8ByteAlignedType, 13);
521 static BSLS_ALIGNMENTIMP_MATCH_FUNC(AlignmentImp16ByteAlignedType, 14);
522 // These types exist, and are needed, only on 32 bit x86 unixe
523
525#else
527#endif
528};
529
530} // close package namespace
531
532#undef BSLS_ALIGNMENTIMP_MATCH_FUNC
533
534
535
536#endif
537
538// ----------------------------------------------------------------------------
539// Copyright 2013 Bloomberg Finance L.P.
540//
541// Licensed under the Apache License, Version 2.0 (the "License");
542// you may not use this file except in compliance with the License.
543// You may obtain a copy of the License at
544//
545// http://www.apache.org/licenses/LICENSE-2.0
546//
547// Unless required by applicable law or agreed to in writing, software
548// distributed under the License is distributed on an "AS IS" BASIS,
549// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
550// See the License for the specific language governing permissions and
551// limitations under the License.
552// ----------------------------- END-OF-FILE ----------------------------------
553
554/** @} */
555/** @} */
556/** @} */
#define BSLS_ALIGNMENTIMP_MATCH_FUNC(T, P)
Definition bsls_alignmentimp.h:496
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
Definition bdlt_iso8601util.h:691
Definition bsls_alignmentimp.h:279
AlignmentImpTag< VALUE > Tag
Alias for the unique type for each alignment value.
Definition bsls_alignmentimp.h:319
@ VALUE
Definition bsls_alignmentimp.h:315
Definition bsls_alignmentimp.h:494
AlignmentImp_Priority< 12 > MaxPriority
Definition bsls_alignmentimp.h:526
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:432
short Type
Definition bsls_alignmentimp.h:437
char Type
Definition bsls_alignmentimp.h:442
long double Type
Definition bsls_alignmentimp.h:387
double Type
Definition bsls_alignmentimp.h:392
float Type
Definition bsls_alignmentimp.h:397
void * Type
Definition bsls_alignmentimp.h:407
wchar_t Type
Definition bsls_alignmentimp.h:412
bool Type
Definition bsls_alignmentimp.h:417
long long Type
Definition bsls_alignmentimp.h:422
long Type
Definition bsls_alignmentimp.h:427
Definition bsls_alignmentimp.h:382
Definition bsls_alignmentimp.h:266
char d_dummy[SIZE]
Definition bsls_alignmentimp.h:269
Definition bsls_alignmentimp.h:466