lean cpp library
A lean C++ library providing efficient utility classes for high-performance C++ applications.
|
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