lean cpp library
A lean C++ library providing efficient utility classes for high-performance C++ applications.
alignment.h
00001 /*****************************************************/
00002 /* lean Memory                  (c) Tobias Zirr 2011 */
00003 /*****************************************************/
00004 
00005 #ifndef LEAN_MEMORY_ALIGNMENT
00006 #define LEAN_MEMORY_ALIGNMENT
00007 
00008 #include "../lean.h"
00009 
00010 #ifdef LEAN0X_NO_ALIGN
00011     
00012     #ifdef _MSC_VER
00013         #ifndef alignas
00014 
00015             #define alignas(alignment) __declspec( align(alignment) )
00016         #endif
00017         #ifndef alignof
00018 
00019             namespace lean
00020             {
00021                 namespace memory
00022                 {
00023                     namespace impl
00024                     {
00026                         template <size_t Size, size_t Alignment>
00027                         struct alignof_fix
00028                         {
00029                             LEAN_STATIC_ASSERT(Size != 0U && Alignment != 0U);
00030                             static const size_t alignment = Alignment;
00031                         };
00032                     }
00033                 }
00034             }
00035 
00037             #define alignof(type) ::lean::memory::impl::alignof_fix<sizeof(type), __alignof(type)>::alignment
00038         #endif
00039     #else
00040         #error Unknown compiler, alignment specifiers unavailable.
00041     #endif
00042 
00043 #endif
00044 
00045 namespace lean
00046 {
00047 namespace memory
00048 {
00050     template <size_t Alignment>
00051     struct check_alignment
00052     {
00054         static const bool valid = false;
00055     };
00056 
00057 #ifndef DOXYGEN_SKIP_THIS
00058 
00059     template <> struct check_alignment<1> { static const bool valid = true; };
00060     template <> struct check_alignment<2> { static const bool valid = true; };
00061     template <> struct check_alignment<4> { static const bool valid = true; };
00062     template <> struct check_alignment<8> { static const bool valid = true; };
00063     template <> struct check_alignment<16> { static const bool valid = true; };
00064     template <> struct check_alignment<32> { static const bool valid = true; };
00065     template <> struct check_alignment<64> { static const bool valid = true; };
00066     template <> struct check_alignment<128> { static const bool valid = true; };
00067 
00068 #endif
00069 
00071     template <size_t Alignment, class Integer>
00072     LEAN_INLINE Integer nalign_integer(Integer integer)
00073     {
00074         LEAN_STATIC_ASSERT_MSG_ALT(check_alignment<Alignment>::valid,
00075             "Alignment is required to be power of two.", Alignment_is_required_to_be_power_of_two);
00076 
00077         // Widen BEFORE complement, otherwise higher-order bits might be lost
00078         return integer & ~static_cast<typename int_type<sign_class::no_sign, sizeof(Integer)>::type>(Alignment - 1);
00079     }
00080 
00082     template <size_t Alignment, class Value>
00083     LEAN_INLINE Value* nalign(Value *pointer)
00084     {
00085         return reinterpret_cast<Value*>(
00086             nalign_integer<Alignment>( reinterpret_cast<uintptr_t>(pointer) ) );
00087     }
00088 
00090     template <size_t Alignment, class Integer>
00091     LEAN_INLINE Integer align_integer(Integer integer)
00092     {
00093         LEAN_STATIC_ASSERT_MSG_ALT(check_alignment<Alignment>::valid,
00094             "Alignment is required to be power of two.", Alignment_is_required_to_be_power_of_two);
00095 
00096         integer += (Alignment - 1);
00097         // Widen BEFORE complement, otherwise higher-order bits might be lost
00098         return integer & ~static_cast<typename int_type<sign_class::no_sign, sizeof(Integer)>::type>(Alignment - 1);
00099     }
00100 
00102     template <size_t Alignment, class Value>
00103     LEAN_INLINE Value* align(Value *pointer)
00104     {
00105         return reinterpret_cast<Value*>(
00106             align_integer<Alignment>( reinterpret_cast<uintptr_t>(pointer) ) );
00107     }
00108 
00110     template <size_t Alignment, class Integer>
00111     LEAN_INLINE Integer upper_align_integer(Integer integer)
00112     {
00113         LEAN_STATIC_ASSERT_MSG_ALT(check_alignment<Alignment>::valid,
00114             "Alignment is required to be power of two.", Alignment_is_required_to_be_power_of_two);
00115 
00116         integer += Alignment;
00117         // Widen BEFORE complement, otherwise higher-order bits might be lost
00118         return integer & ~static_cast<typename int_type<sign_class::no_sign, sizeof(Integer)>::type>(Alignment - 1);
00119     }
00120 
00122     template <size_t Alignment, class Value>
00123     LEAN_INLINE Value* upper_align(Value *pointer)
00124     {
00125         return reinterpret_cast<Value*>(
00126             upper_align_integer<Alignment>( reinterpret_cast<uintptr_t>(pointer) ) );
00127     }
00128 
00130 
00132     template <size_t Alignment>
00133     struct stack_aligned
00134     {
00135         // Always checked, therefore use static_assert with care
00136         LEAN_STATIC_ASSERT_MSG_ALT(Alignment & ~Alignment, // = false, dependent
00137             "Alignment is required to be power of two.",
00138             Alignment_is_required_to_be_power_of_two);
00139     };
00140 
00141 #ifndef DOXYGEN_SKIP_THIS
00142 
00143 #ifdef _MSC_VER
00144     // MSC adds padding to make the size of aligned structures a multiple of their alignment...
00145     #pragma warning(push)
00146     #pragma warning(disable : 4324)
00147 #endif
00148 
00149     template <> struct alignas(1) stack_aligned<1> { };
00150     template <> struct alignas(2) stack_aligned<2> { };
00151     template <> struct alignas(4) stack_aligned<4> { };
00152     template <> struct alignas(8) stack_aligned<8> { };
00153     template <> struct alignas(16) stack_aligned<16> { };
00154     template <> struct alignas(32) stack_aligned<32> { };
00155     template <> struct alignas(64) stack_aligned<64> { };
00156     template <> struct alignas(128) stack_aligned<128> { };
00157 
00158 #ifdef _MSC_VER
00159     #pragma warning(pop)
00160 #endif
00161 
00162 #endif
00163 
00164 } // namespace
00165 
00166 using memory::check_alignment;
00167 using memory::stack_aligned;
00168 
00169 } // namespace
00170 
00171 #endif