1 /* Copyright 2015 The TensorFlow Authors. All Rights Reserved. 2 3 Licensed under the Apache License, Version 2.0 (the "License"); 4 you may not use this file except in compliance with the License. 5 You may obtain a copy of the License at 6 7 http://www.apache.org/licenses/LICENSE-2.0 8 9 Unless required by applicable law or agreed to in writing, software 10 distributed under the License is distributed on an "AS IS" BASIS, 11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 See the License for the specific language governing permissions and 13 limitations under the License. 14 ==============================================================================*/ 15 16 // ManualConstructor statically-allocates space in which to store some 17 // object, but does not initialize it. You can then call the constructor 18 // and destructor for the object yourself as you see fit. This is useful 19 // for memory management optimizations, where you want to initialize and 20 // destroy an object multiple times but only allocate it once. 21 // 22 // (When I say ManualConstructor statically allocates space, I mean that 23 // the ManualConstructor object itself is forced to be the right size.) 24 25 #ifndef TENSORFLOW_LIB_GTL_MANUAL_CONSTRUCTOR_H_ 26 #define TENSORFLOW_LIB_GTL_MANUAL_CONSTRUCTOR_H_ 27 28 #include <stddef.h> 29 #include <new> 30 #include <utility> 31 32 #include "tensorflow/core/platform/macros.h" 33 #include "tensorflow/core/platform/mem.h" 34 35 namespace tensorflow { 36 namespace gtl { 37 namespace internal { 38 39 // 40 // Provides a char array with the exact same alignment as another type. The 41 // first parameter must be a complete type, the second parameter is how many 42 // of that type to provide space for. 43 // 44 // TF_LIB_GTL_ALIGNED_CHAR_ARRAY(struct stat, 16) storage_; 45 // 46 // Because MSVC and older GCCs require that the argument to their alignment 47 // construct to be a literal constant integer, we use a template instantiated 48 // at all the possible powers of two. 49 #ifndef SWIG 50 template <int alignment, int size> 51 struct AlignType {}; 52 template <int size> 53 struct AlignType<0, size> { 54 typedef char result[size]; 55 }; 56 #if defined(_MSC_VER) 57 #define TF_LIB_GTL_ALIGN_ATTRIBUTE(X) __declspec(align(X)) 58 #define TF_LIB_GTL_ALIGN_OF(T) __alignof(T) 59 #elif defined(COMPILER_GCC3) || __GNUC__ >= 3 || defined(__APPLE__) || \ 60 defined(COMPILER_ICC) || defined(OS_NACL) || defined(__clang__) 61 #define TF_LIB_GTL_ALIGN_ATTRIBUTE(X) __attribute__((aligned(X))) 62 #define TF_LIB_GTL_ALIGN_OF(T) __alignof__(T) 63 #endif 64 65 #if defined(TF_LIB_GTL_ALIGN_ATTRIBUTE) 66 67 #define TF_LIB_GTL_ALIGNTYPE_TEMPLATE(X) \ 68 template <int size> \ 69 struct AlignType<X, size> { \ 70 typedef TF_LIB_GTL_ALIGN_ATTRIBUTE(X) char result[size]; \ 71 } 72 73 TF_LIB_GTL_ALIGNTYPE_TEMPLATE(1); 74 TF_LIB_GTL_ALIGNTYPE_TEMPLATE(2); 75 TF_LIB_GTL_ALIGNTYPE_TEMPLATE(4); 76 TF_LIB_GTL_ALIGNTYPE_TEMPLATE(8); 77 TF_LIB_GTL_ALIGNTYPE_TEMPLATE(16); 78 TF_LIB_GTL_ALIGNTYPE_TEMPLATE(32); 79 TF_LIB_GTL_ALIGNTYPE_TEMPLATE(64); 80 TF_LIB_GTL_ALIGNTYPE_TEMPLATE(128); 81 TF_LIB_GTL_ALIGNTYPE_TEMPLATE(256); 82 TF_LIB_GTL_ALIGNTYPE_TEMPLATE(512); 83 TF_LIB_GTL_ALIGNTYPE_TEMPLATE(1024); 84 TF_LIB_GTL_ALIGNTYPE_TEMPLATE(2048); 85 TF_LIB_GTL_ALIGNTYPE_TEMPLATE(4096); 86 TF_LIB_GTL_ALIGNTYPE_TEMPLATE(8192); 87 // Any larger and MSVC++ will complain. 88 89 #define TF_LIB_GTL_ALIGNED_CHAR_ARRAY(T, Size) \ 90 typename tensorflow::gtl::internal::AlignType<TF_LIB_GTL_ALIGN_OF(T), \ 91 sizeof(T) * Size>::result 92 93 #undef TF_LIB_GTL_ALIGNTYPE_TEMPLATE 94 #undef TF_LIB_GTL_ALIGN_ATTRIBUTE 95 96 #else // defined(TF_LIB_GTL_ALIGN_ATTRIBUTE) 97 #error "You must define TF_LIB_GTL_ALIGNED_CHAR_ARRAY for your compiler." 98 #endif // defined(TF_LIB_GTL_ALIGN_ATTRIBUTE) 99 100 #else // !SWIG 101 102 // SWIG can't represent alignment and doesn't care about alignment on data 103 // members (it works fine without it). 104 template <typename Size> 105 struct AlignType { 106 typedef char result[Size]; 107 }; 108 #define TF_LIB_GTL_ALIGNED_CHAR_ARRAY(T, Size) \ 109 tensorflow::gtl::internal::AlignType<Size * sizeof(T)>::result 110 111 // Enough to parse with SWIG, will never be used by running code. 112 #define TF_LIB_GTL_ALIGN_OF(Type) 16 113 114 #endif // !SWIG 115 116 } // namespace internal 117 } // namespace gtl 118 119 template <typename Type> 120 class ManualConstructor { 121 public: 122 // No constructor or destructor because one of the most useful uses of 123 // this class is as part of a union, and members of a union cannot have 124 // constructors or destructors. And, anyway, the whole point of this 125 // class is to bypass these. 126 127 // Support users creating arrays of ManualConstructor<>s. This ensures that 128 // the array itself has the correct alignment. 129 static void* operator new[](size_t size) { 130 return port::AlignedMalloc(size, TF_LIB_GTL_ALIGN_OF(Type)); 131 } 132 static void operator delete[](void* mem) { port::AlignedFree(mem); } 133 134 inline Type* get() { return reinterpret_cast<Type*>(space_); } 135 inline const Type* get() const { 136 return reinterpret_cast<const Type*>(space_); 137 } 138 139 inline Type* operator->() { return get(); } 140 inline const Type* operator->() const { return get(); } 141 142 inline Type& operator*() { return *get(); } 143 inline const Type& operator*() const { return *get(); } 144 145 inline void Init() { new (space_) Type; } 146 147 // Init() constructs the Type instance using the given arguments 148 // (which are forwarded to Type's constructor). In C++11, Init() can 149 // take any number of arguments of any type, and forwards them perfectly. 150 // On pre-C++11 platforms, it can take up to 11 arguments, and may not be 151 // able to forward certain kinds of arguments. 152 // 153 // Note that Init() with no arguments performs default-initialization, 154 // not zero-initialization (i.e it behaves the same as "new Type;", not 155 // "new Type();"), so it will leave non-class types uninitialized. 156 #ifdef LANG_CXX11 157 template <typename... Ts> 158 inline void Init(Ts&&... args) { // NOLINT 159 new (space_) Type(std::forward<Ts>(args)...); // NOLINT 160 } 161 #else // !defined(LANG_CXX11) 162 template <typename T1> 163 inline void Init(const T1& p1) { 164 new (space_) Type(p1); 165 } 166 167 template <typename T1, typename T2> 168 inline void Init(const T1& p1, const T2& p2) { 169 new (space_) Type(p1, p2); 170 } 171 172 template <typename T1, typename T2, typename T3> 173 inline void Init(const T1& p1, const T2& p2, const T3& p3) { 174 new (space_) Type(p1, p2, p3); 175 } 176 177 template <typename T1, typename T2, typename T3, typename T4> 178 inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4) { 179 new (space_) Type(p1, p2, p3, p4); 180 } 181 182 template <typename T1, typename T2, typename T3, typename T4, typename T5> 183 inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4, 184 const T5& p5) { 185 new (space_) Type(p1, p2, p3, p4, p5); 186 } 187 188 template <typename T1, typename T2, typename T3, typename T4, typename T5, 189 typename T6> 190 inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4, 191 const T5& p5, const T6& p6) { 192 new (space_) Type(p1, p2, p3, p4, p5, p6); 193 } 194 195 template <typename T1, typename T2, typename T3, typename T4, typename T5, 196 typename T6, typename T7> 197 inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4, 198 const T5& p5, const T6& p6, const T7& p7) { 199 new (space_) Type(p1, p2, p3, p4, p5, p6, p7); 200 } 201 202 template <typename T1, typename T2, typename T3, typename T4, typename T5, 203 typename T6, typename T7, typename T8> 204 inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4, 205 const T5& p5, const T6& p6, const T7& p7, const T8& p8) { 206 new (space_) Type(p1, p2, p3, p4, p5, p6, p7, p8); 207 } 208 209 template <typename T1, typename T2, typename T3, typename T4, typename T5, 210 typename T6, typename T7, typename T8, typename T9> 211 inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4, 212 const T5& p5, const T6& p6, const T7& p7, const T8& p8, 213 const T9& p9) { 214 new (space_) Type(p1, p2, p3, p4, p5, p6, p7, p8, p9); 215 } 216 217 template <typename T1, typename T2, typename T3, typename T4, typename T5, 218 typename T6, typename T7, typename T8, typename T9, typename T10> 219 inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4, 220 const T5& p5, const T6& p6, const T7& p7, const T8& p8, 221 const T9& p9, const T10& p10) { 222 new (space_) Type(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10); 223 } 224 225 template <typename T1, typename T2, typename T3, typename T4, typename T5, 226 typename T6, typename T7, typename T8, typename T9, typename T10, 227 typename T11> 228 inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4, 229 const T5& p5, const T6& p6, const T7& p7, const T8& p8, 230 const T9& p9, const T10& p10, const T11& p11) { 231 new (space_) Type(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11); 232 } 233 #endif // LANG_CXX11 234 235 inline void Destroy() { get()->~Type(); } 236 237 private: 238 TF_LIB_GTL_ALIGNED_CHAR_ARRAY(Type, 1) space_; 239 }; 240 241 #undef TF_LIB_GTL_ALIGNED_CHAR_ARRAY 242 #undef TF_LIB_GTL_ALIGN_OF 243 244 } // namespace tensorflow 245 246 #endif // TENSORFLOW_LIB_GTL_MANUAL_CONSTRUCTOR_H_ 247