/Users/deen/code/yugabyte-db/src/yb/gutil/manual_constructor.h
Line | Count | Source |
1 | | // Copyright (c) 2006, Google Inc. |
2 | | // All rights reserved. |
3 | | // |
4 | | // Redistribution and use in source and binary forms, with or without |
5 | | // modification, are permitted provided that the following conditions are |
6 | | // met: |
7 | | // |
8 | | // * Redistributions of source code must retain the above copyright |
9 | | // notice, this list of conditions and the following disclaimer. |
10 | | // * Redistributions in binary form must reproduce the above |
11 | | // copyright notice, this list of conditions and the following disclaimer |
12 | | // in the documentation and/or other materials provided with the |
13 | | // distribution. |
14 | | // * Neither the name of Google Inc. nor the names of its |
15 | | // contributors may be used to endorse or promote products derived from |
16 | | // this software without specific prior written permission. |
17 | | // |
18 | | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
19 | | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
20 | | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
21 | | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
22 | | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
23 | | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
24 | | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
25 | | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
26 | | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
27 | | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
28 | | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
29 | | // --- |
30 | | // |
31 | | // |
32 | | // ManualConstructor statically-allocates space in which to store some |
33 | | // object, but does not initialize it. You can then call the constructor |
34 | | // and destructor for the object yourself as you see fit. This is useful |
35 | | // for memory management optimizations, where you want to initialize and |
36 | | // destroy an object multiple times but only allocate it once. |
37 | | // |
38 | | // (When I say ManualConstructor statically allocates space, I mean that |
39 | | // the ManualConstructor object itself is forced to be the right size.) |
40 | | // |
41 | | // For example usage, check out util/gtl/small_map.h. |
42 | | |
43 | | // |
44 | | // The following only applies to changes made to this file as part of YugaByte development. |
45 | | // |
46 | | // Portions Copyright (c) YugaByte, Inc. |
47 | | // |
48 | | // Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except |
49 | | // in compliance with the License. You may obtain a copy of the License at |
50 | | // |
51 | | // http://www.apache.org/licenses/LICENSE-2.0 |
52 | | // |
53 | | // Unless required by applicable law or agreed to in writing, software distributed under the License |
54 | | // is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express |
55 | | // or implied. See the License for the specific language governing permissions and limitations |
56 | | // under the License. |
57 | | // |
58 | | #ifndef UTIL_GTL_MANUAL_CONSTRUCTOR_H_ |
59 | | #define UTIL_GTL_MANUAL_CONSTRUCTOR_H_ |
60 | | |
61 | | #include <stddef.h> |
62 | | |
63 | | #include "yb/gutil/port.h" |
64 | | |
65 | | namespace base { |
66 | | |
67 | | namespace util { |
68 | | namespace gtl { |
69 | | namespace internal { |
70 | | |
71 | | // |
72 | | // Provides a char array with the exact same alignment as another type. The |
73 | | // first parameter must be a complete type, the second parameter is how many |
74 | | // of that type to provide space for. |
75 | | // |
76 | | // UTIL_GTL_ALIGNED_CHAR_ARRAY(struct stat, 16) storage_; |
77 | | // |
78 | | // Because MSVC and older GCCs require that the argument to their alignment |
79 | | // construct to be a literal constant integer, we use a template instantiated |
80 | | // at all the possible powers of two. |
81 | | #ifndef SWIG |
82 | | template<int alignment, int size> struct AlignType { }; |
83 | | template<int size> struct AlignType<0, size> { typedef char result[size]; }; |
84 | | #if defined(_MSC_VER) |
85 | | #define UTIL_GTL_ALIGN_ATTRIBUTE(X) __declspec(align(X)) |
86 | | #define UTIL_GTL_ALIGN_OF(T) __alignof(T) |
87 | | #elif defined(__GNUC__) || defined(__APPLE__) || defined(__INTEL_COMPILER) \ |
88 | | || defined(__nacl__) |
89 | | #define UTIL_GTL_ALIGN_ATTRIBUTE(X) __attribute__((aligned(X))) |
90 | | #define UTIL_GTL_ALIGN_OF(T) __alignof__(T) |
91 | | #endif |
92 | | |
93 | | #if defined(UTIL_GTL_ALIGN_ATTRIBUTE) |
94 | | |
95 | | #define UTIL_GTL_ALIGNTYPE_TEMPLATE(X) \ |
96 | | template<int size> struct AlignType<X, size> { \ |
97 | | typedef UTIL_GTL_ALIGN_ATTRIBUTE(X) char result[size]; \ |
98 | | } |
99 | | |
100 | | UTIL_GTL_ALIGNTYPE_TEMPLATE(1); |
101 | | UTIL_GTL_ALIGNTYPE_TEMPLATE(2); |
102 | | UTIL_GTL_ALIGNTYPE_TEMPLATE(4); |
103 | | UTIL_GTL_ALIGNTYPE_TEMPLATE(8); |
104 | | UTIL_GTL_ALIGNTYPE_TEMPLATE(16); |
105 | | UTIL_GTL_ALIGNTYPE_TEMPLATE(32); |
106 | | UTIL_GTL_ALIGNTYPE_TEMPLATE(64); |
107 | | UTIL_GTL_ALIGNTYPE_TEMPLATE(128); |
108 | | UTIL_GTL_ALIGNTYPE_TEMPLATE(256); |
109 | | UTIL_GTL_ALIGNTYPE_TEMPLATE(512); |
110 | | UTIL_GTL_ALIGNTYPE_TEMPLATE(1024); |
111 | | UTIL_GTL_ALIGNTYPE_TEMPLATE(2048); |
112 | | UTIL_GTL_ALIGNTYPE_TEMPLATE(4096); |
113 | | UTIL_GTL_ALIGNTYPE_TEMPLATE(8192); |
114 | | // Any larger and MSVC++ will complain. |
115 | | |
116 | | #define UTIL_GTL_ALIGNED_CHAR_ARRAY(T, Size) \ |
117 | | typename util::gtl::internal::AlignType<UTIL_GTL_ALIGN_OF(T), \ |
118 | | sizeof(T) * Size>::result |
119 | | |
120 | | #undef UTIL_GTL_ALIGNTYPE_TEMPLATE |
121 | | #undef UTIL_GTL_ALIGN_ATTRIBUTE |
122 | | |
123 | | #else // defined(UTIL_GTL_ALIGN_ATTRIBUTE) |
124 | | #error "You must define UTIL_GTL_ALIGNED_CHAR_ARRAY for your compiler." |
125 | | #endif // defined(UTIL_GTL_ALIGN_ATTRIBUTE) |
126 | | |
127 | | #else // !SWIG |
128 | | |
129 | | // SWIG can't represent alignment and doesn't care about alignment on data |
130 | | // members (it works fine without it). |
131 | | template<typename Size> |
132 | | struct AlignType { typedef char result[Size]; }; |
133 | | #define UTIL_GTL_ALIGNED_CHAR_ARRAY(T, Size) \ |
134 | | util::gtl::internal::AlignType<Size * sizeof(T)>::result |
135 | | |
136 | | // Enough to parse with SWIG, will never be used by running code. |
137 | | #define UTIL_GTL_ALIGN_OF(Type) 16 |
138 | | |
139 | | #endif // !SWIG |
140 | | |
141 | | } // namespace internal |
142 | | } // namespace gtl |
143 | | } // namespace util |
144 | | |
145 | | template <typename Type> |
146 | | class ManualConstructor { |
147 | | public: |
148 | | // No constructor or destructor because one of the most useful uses of |
149 | | // this class is as part of a union, and members of a union cannot have |
150 | | // constructors or destructors. And, anyway, the whole point of this |
151 | | // class is to bypass these. |
152 | | |
153 | | // Support users creating arrays of ManualConstructor<>s. This ensures that |
154 | | // the array itself has the correct alignment. |
155 | | static void* operator new[](size_t size) { |
156 | | return aligned_malloc(size, UTIL_GTL_ALIGN_OF(Type)); |
157 | | } |
158 | | static void operator delete[](void* mem) { |
159 | | aligned_free(mem); |
160 | | } |
161 | | |
162 | 8 | inline Type* get() { |
163 | 8 | return reinterpret_cast<Type*>(space_); |
164 | 8 | } |
165 | | inline const Type* get() const { |
166 | | return reinterpret_cast<const Type*>(space_); |
167 | | } |
168 | | |
169 | | inline Type* operator->() { return get(); } |
170 | | inline const Type* operator->() const { return get(); } |
171 | | |
172 | | inline Type& operator*() { return *get(); } |
173 | | inline const Type& operator*() const { return *get(); } |
174 | | |
175 | | // You can pass up to four constructor arguments as arguments of Init(). |
176 | 4 | inline void Init() { |
177 | 4 | new(space_) Type; |
178 | 4 | } |
179 | | |
180 | | template <typename T1> |
181 | | inline void Init(const T1& p1) { |
182 | | new(space_) Type(p1); |
183 | | } |
184 | | |
185 | | template <typename T1, typename T2> |
186 | | inline void Init(const T1& p1, const T2& p2) { |
187 | | new(space_) Type(p1, p2); |
188 | | } |
189 | | |
190 | | template <typename T1, typename T2, typename T3> |
191 | | inline void Init(const T1& p1, const T2& p2, const T3& p3) { |
192 | | new(space_) Type(p1, p2, p3); |
193 | | } |
194 | | |
195 | | template <typename T1, typename T2, typename T3, typename T4> |
196 | | inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4) { |
197 | | new(space_) Type(p1, p2, p3, p4); |
198 | | } |
199 | | |
200 | | template <typename T1, typename T2, typename T3, typename T4, typename T5> |
201 | | inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4, |
202 | | const T5& p5) { |
203 | | new(space_) Type(p1, p2, p3, p4, p5); |
204 | | } |
205 | | |
206 | | template <typename T1, typename T2, typename T3, typename T4, typename T5, |
207 | | typename T6> |
208 | | inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4, |
209 | | const T5& p5, const T6& p6) { |
210 | | new(space_) Type(p1, p2, p3, p4, p5, p6); |
211 | | } |
212 | | |
213 | | template <typename T1, typename T2, typename T3, typename T4, typename T5, |
214 | | typename T6, typename T7> |
215 | | inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4, |
216 | | const T5& p5, const T6& p6, const T7& p7) { |
217 | | new(space_) Type(p1, p2, p3, p4, p5, p6, p7); |
218 | | } |
219 | | |
220 | | template <typename T1, typename T2, typename T3, typename T4, typename T5, |
221 | | typename T6, typename T7, typename T8> |
222 | | inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4, |
223 | | const T5& p5, const T6& p6, const T7& p7, const T8& p8) { |
224 | | new(space_) Type(p1, p2, p3, p4, p5, p6, p7, p8); |
225 | | } |
226 | | |
227 | | template <typename T1, typename T2, typename T3, typename T4, typename T5, |
228 | | typename T6, typename T7, typename T8, typename T9> |
229 | | inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4, |
230 | | const T5& p5, const T6& p6, const T7& p7, const T8& p8, |
231 | | const T9& p9) { |
232 | | new(space_) Type(p1, p2, p3, p4, p5, p6, p7, p8, p9); |
233 | | } |
234 | | |
235 | | template <typename T1, typename T2, typename T3, typename T4, typename T5, |
236 | | typename T6, typename T7, typename T8, typename T9, typename T10> |
237 | | inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4, |
238 | | const T5& p5, const T6& p6, const T7& p7, const T8& p8, |
239 | | const T9& p9, const T10& p10) { |
240 | | new(space_) Type(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10); |
241 | | } |
242 | | |
243 | | template <typename T1, typename T2, typename T3, typename T4, typename T5, |
244 | | typename T6, typename T7, typename T8, typename T9, typename T10, |
245 | | typename T11> |
246 | | inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4, |
247 | | const T5& p5, const T6& p6, const T7& p7, const T8& p8, |
248 | | const T9& p9, const T10& p10, const T11& p11) { |
249 | | new(space_) Type(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11); |
250 | | } |
251 | | |
252 | 4 | inline void Destroy() { |
253 | 4 | get()->~Type(); |
254 | 4 | } |
255 | | |
256 | | private: |
257 | | UTIL_GTL_ALIGNED_CHAR_ARRAY(Type, 1) space_; |
258 | | }; |
259 | | |
260 | | #undef UTIL_GTL_ALIGNED_CHAR_ARRAY |
261 | | #undef UTIL_GTL_ALIGN_OF |
262 | | |
263 | | } |
264 | | |
265 | | #endif // UTIL_GTL_MANUAL_CONSTRUCTOR_H_ |