• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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