]>
Commit | Line | Data |
---|---|---|
3038054c BI |
1 | /* metaprogramming.h -*- C++ -*- |
2 | * | |
2e01cda6 | 3 | * Copyright (C) 2012-2016, Intel Corporation |
3038054c BI |
4 | * All rights reserved. |
5 | * | |
3038054c BI |
6 | * Redistribution and use in source and binary forms, with or without |
7 | * modification, are permitted provided that the following conditions | |
8 | * are met: | |
9 | * | |
10 | * * Redistributions of source code must retain the above copyright | |
11 | * notice, this list of conditions and the following disclaimer. | |
12 | * * Redistributions in binary form must reproduce the above copyright | |
13 | * notice, this list of conditions and the following disclaimer in | |
14 | * the documentation and/or other materials provided with the | |
15 | * distribution. | |
16 | * * Neither the name of Intel Corporation nor the names of its | |
17 | * contributors may be used to endorse or promote products derived | |
18 | * from this software without specific prior written permission. | |
19 | * | |
3038054c BI |
20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
23 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
24 | * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, | |
25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, | |
26 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS | |
27 | * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED | |
28 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
29 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY | |
30 | * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
31 | * POSSIBILITY OF SUCH DAMAGE. | |
2e01cda6 IV |
32 | * |
33 | * ********************************************************************* | |
34 | * | |
35 | * PLEASE NOTE: This file is a downstream copy of a file mainitained in | |
36 | * a repository at cilkplus.org. Changes made to this file that are not | |
37 | * submitted through the contribution process detailed at | |
38 | * http://www.cilkplus.org/submit-cilk-contribution will be lost the next | |
39 | * time that a new version is released. Changes only submitted to the | |
40 | * GNU compiler collection or posted to the git repository at | |
41 | * https://bitbucket.org/intelcilkruntime/intel-cilk-runtime.git are | |
42 | * not tracked. | |
43 | * | |
44 | * We welcome your contributions to this open source project. Thank you | |
45 | * for your assistance in helping us improve Cilk Plus. | |
3038054c BI |
46 | */ |
47 | ||
48 | /** @file metaprogramming.h | |
49 | * | |
2e01cda6 | 50 | * @brief Defines metaprogramming utility classes used in the Intel(R) Cilk(TM) Plus library. |
3038054c BI |
51 | * |
52 | * @ingroup common | |
53 | */ | |
54 | ||
55 | #ifndef METAPROGRAMMING_H_INCLUDED | |
56 | #define METAPROGRAMMING_H_INCLUDED | |
57 | ||
58 | #ifdef __cplusplus | |
59 | ||
60 | #include <functional> | |
61 | #include <new> | |
62 | #include <cstdlib> | |
63 | #ifdef _WIN32 | |
64 | #include <malloc.h> | |
65 | #endif | |
66 | #include <algorithm> | |
67 | ||
68 | namespace cilk { | |
69 | ||
70 | namespace internal { | |
71 | ||
72 | /** Test if a class is empty. | |
73 | * | |
74 | * If @a Class is an empty (and therefore necessarily stateless) class, then | |
2e01cda6 | 75 | * the "empty base-class optimization" guarantees that |
3038054c BI |
76 | * `sizeof(check_for_empty_class<Class>) == sizeof(char)`. Conversely, if |
77 | * `sizeof(check_for_empty_class<Class>) > sizeof(char)`, then @a Class is not | |
78 | * empty, and we must discriminate distinct instances of @a Class. | |
79 | * | |
80 | * Typical usage: | |
81 | * | |
82 | * // General definition of A<B> for non-empty B: | |
83 | * template <typename B, bool BIsEmpty = class_is_empty<B>::value> > | |
84 | * class A { ... }; | |
85 | * | |
86 | * // Specialized definition of A<B> for empty B: | |
87 | * template <typename B> | |
88 | * class A<B, true> { ... }; | |
89 | * | |
90 | * @tparam Class The class to be tested for emptiness. | |
91 | * | |
92 | * @result The `value` member will be `true` if @a Class is empty, | |
93 | * `false` otherwise. | |
94 | * | |
95 | * @ingroup common | |
96 | */ | |
97 | template <class Class> | |
2e01cda6 | 98 | class class_is_empty { |
3038054c BI |
99 | class check_for_empty_class : public Class |
100 | { | |
101 | char m_data; | |
102 | public: | |
103 | // Declared but not defined | |
104 | check_for_empty_class(); | |
105 | check_for_empty_class(const check_for_empty_class&); | |
106 | check_for_empty_class& operator=(const check_for_empty_class&); | |
107 | ~check_for_empty_class(); | |
108 | }; | |
109 | public: | |
110 | ||
111 | /** Constant is true if and only if @a Class is empty. | |
112 | */ | |
113 | static const bool value = (sizeof(check_for_empty_class) == sizeof(char)); | |
114 | }; | |
115 | ||
116 | ||
117 | /** Get the alignment of a type. | |
118 | * | |
119 | * For example: | |
120 | * | |
121 | * align_of<double>::value == 8 | |
122 | * | |
123 | * @tparam Tp The type whose alignment is to be computed. | |
124 | * | |
125 | * @result The `value` member of an instantiation of this class template | |
126 | * will hold the integral alignment requirement of @a Tp. | |
127 | * | |
128 | * @pre @a Tp shall be a complete type. | |
129 | * | |
130 | * @ingroup common | |
131 | */ | |
132 | template <typename Tp> | |
133 | struct align_of | |
134 | { | |
135 | private: | |
136 | struct imp { | |
137 | char m_padding; | |
138 | Tp m_val; | |
139 | ||
140 | // The following declarations exist to suppress compiler-generated | |
141 | // definitions, in case @a Tp does not have a public default | |
142 | // constructor, copy constructor, or destructor. | |
143 | imp(const imp&); // Declared but not defined | |
144 | ~imp(); // Declared but not defined | |
145 | }; | |
146 | ||
147 | public: | |
148 | /// The integral alignment requirement of @a Tp. | |
149 | static const std::size_t value = (sizeof(imp) - sizeof(Tp)); | |
150 | }; | |
151 | ||
152 | ||
153 | /** A class containing raw bytes with a specified alignment and size. | |
154 | * | |
155 | * An object of type `aligned_storage<S, A>` will have alignment `A` and | |
156 | * size at least `S`. Its contents will be uninitialized bytes. | |
157 | * | |
158 | * @tparam Size The required minimum size of the resulting class. | |
159 | * @tparam Alignment The required alignment of the resulting class. | |
160 | * | |
2e01cda6 | 161 | * @pre @a Alignment shall be a power of 2 no greater than 64. |
3038054c BI |
162 | * |
163 | * @note This is implemented using the `CILK_ALIGNAS` macro, which uses | |
164 | * the non-standard, implementation-specific features | |
2e01cda6 | 165 | * `__declspec(align(N))` on Windows, and |
3038054c BI |
166 | * `__attribute__((__aligned__(N)))` on Unix. The `gcc` implementation |
167 | * of `__attribute__((__aligned__(N)))` requires a numeric literal `N` | |
168 | * (_not_ an arbitrary compile-time constant expression). Therefore, | |
169 | * this class is implemented using specialization on the required | |
170 | * alignment. | |
171 | * | |
172 | * @note The template class is specialized only for the supported | |
173 | * alignments. An attempt to instantiate it for an unsupported | |
174 | * alignment will result in a compilation error. | |
175 | */ | |
176 | template <std::size_t Size, std::size_t Alignment> | |
177 | struct aligned_storage; | |
178 | ||
2e01cda6 IV |
179 | /// @cond |
180 | template<std::size_t Size> class aligned_storage<Size, 1> | |
3038054c | 181 | { CILK_ALIGNAS( 1) char m_bytes[Size]; }; |
2e01cda6 | 182 | template<std::size_t Size> class aligned_storage<Size, 2> |
3038054c | 183 | { CILK_ALIGNAS( 2) char m_bytes[Size]; }; |
2e01cda6 | 184 | template<std::size_t Size> class aligned_storage<Size, 4> |
3038054c | 185 | { CILK_ALIGNAS( 4) char m_bytes[Size]; }; |
2e01cda6 | 186 | template<std::size_t Size> class aligned_storage<Size, 8> |
3038054c | 187 | { CILK_ALIGNAS( 8) char m_bytes[Size]; }; |
2e01cda6 | 188 | template<std::size_t Size> class aligned_storage<Size, 16> |
3038054c | 189 | { CILK_ALIGNAS(16) char m_bytes[Size]; }; |
2e01cda6 | 190 | template<std::size_t Size> class aligned_storage<Size, 32> |
3038054c | 191 | { CILK_ALIGNAS(32) char m_bytes[Size]; }; |
2e01cda6 | 192 | template<std::size_t Size> class aligned_storage<Size, 64> |
3038054c | 193 | { CILK_ALIGNAS(64) char m_bytes[Size]; }; |
2e01cda6 | 194 | /// @endcond |
3038054c BI |
195 | |
196 | /** A buffer of uninitialized bytes with the same size and alignment as a | |
197 | * specified type. | |
198 | * | |
199 | * The class `storage_for_object<Type>` will have the same size and alignment | |
200 | * properties as `Type`, but it will contain only raw (uninitialized) bytes. | |
201 | * This allows the definition of a data member which can contain a `Type` | |
202 | * object which is initialized explicitly under program control, rather | |
2e01cda6 | 203 | * than implicitly as part of the initialization of the containing class. |
3038054c BI |
204 | * For example: |
205 | * | |
206 | * class C { | |
207 | * storage_for_object<MemberClass> _member; | |
208 | * public: | |
209 | * C() ... // Does NOT initialize _member | |
2e01cda6 | 210 | * void initialize(args) |
3038054c BI |
211 | * { new (_member.pointer()) MemberClass(args); } |
212 | * const MemberClass& member() const { return _member.object(); } | |
213 | * MemberClass& member() { return _member.object(); } | |
214 | * | |
215 | * @tparam Type The type whose size and alignment are to be reflected | |
216 | * by this class. | |
217 | */ | |
218 | template <typename Type> | |
2e01cda6 | 219 | class storage_for_object : |
3038054c BI |
220 | aligned_storage< sizeof(Type), align_of<Type>::value > |
221 | { | |
222 | public: | |
223 | /// Return a typed reference to the buffer. | |
224 | const Type& object() const { return *reinterpret_cast<Type*>(this); } | |
2e01cda6 | 225 | /// Return a typed reference to the buffer. |
3038054c BI |
226 | Type& object() { return *reinterpret_cast<Type*>(this); } |
227 | }; | |
228 | ||
229 | ||
230 | /** Get the functor class corresponding to a binary function type. | |
231 | * | |
2e01cda6 | 232 | * The `binary_functor` template class can be instantiated with a binary |
3038054c | 233 | * functor class or with a real binary function, and will yield an equivalent |
2e01cda6 | 234 | * binary functor class in either case. |
3038054c BI |
235 | * |
236 | * @tparam F A binary functor class, a binary function type, or a pointer to | |
237 | * binary function type. | |
238 | * | |
239 | * @result `binary_functor<F>::%type` will be the same as @a F if @a F is | |
240 | * a class. It will be a `std::pointer_to_binary_function` wrapper | |
241 | * if @a F is a binary function or binary function pointer type. | |
242 | * (It will _not_ necessarily be an `Adaptable Binary Function` | |
243 | * class, since @a F might be a non-adaptable binary functor | |
244 | * class.) | |
245 | * | |
246 | * @ingroup common | |
247 | */ | |
248 | template <typename F> | |
249 | struct binary_functor { | |
250 | /// The binary functor class equivalent to @a F. | |
251 | typedef F type; | |
252 | }; | |
253 | ||
254 | /// @copydoc binary_functor | |
255 | /// Specialization for binary function. | |
256 | template <typename R, typename A, typename B> | |
257 | struct binary_functor<R(A,B)> { | |
258 | /// The binary functor class equivalent to @a F. | |
259 | typedef std::pointer_to_binary_function<A, B, R> type; | |
260 | }; | |
261 | ||
262 | /// @copydoc binary_functor | |
263 | /// Specialization for pointer to binary function. | |
264 | template <typename R, typename A, typename B> | |
265 | struct binary_functor<R(*)(A,B)> { | |
266 | /// The binary functor class equivalent to @a F. | |
267 | typedef std::pointer_to_binary_function<A, B, R> type; | |
268 | }; | |
269 | ||
270 | ||
271 | /** Indirect binary function class with specified types. | |
272 | * | |
273 | * `typed_indirect_binary_function<F>` is an `Adaptable Binary Function` class | |
274 | * based on an existing binary functor class or binary function type @a F. If | |
275 | * @a F is a stateless class, then this class will be empty, and its | |
2e01cda6 | 276 | * `operator()` will invoke @a F's `operator()`. Otherwise, an object of this |
3038054c BI |
277 | * class will hold a pointer to an object of type @a F, and will refer its |
278 | * `operator()` calls to the pointed-to @a F object. | |
279 | * | |
280 | * That is, suppose that we have the declarations: | |
281 | * | |
282 | * F *p; | |
283 | * typed_indirect_binary_function<F, int, int, bool> ibf(p); | |
284 | * | |
285 | * Then: | |
286 | * | |
287 | * - `ibf(x, y) == (*p)(x, y)`. | |
288 | * - `ibf(x, y)` will not do a pointer dereference if `F` is an empty class. | |
289 | * | |
290 | * @note Just to repeat: if `F` is an empty class, then | |
291 | * `typed_indirect_binary_function\<F\>' is also an empty class. | |
2e01cda6 IV |
292 | * This is critical for its use in the |
293 | * @ref cilk::cilk_lib_1_1::min_max_internal::view_base | |
3038054c BI |
294 | * "min/max reducer view classes", where it allows the view to |
295 | * call a comparison functor in the monoid without actually | |
2e01cda6 | 296 | * having to allocate a pointer in the view class when the |
3038054c BI |
297 | * comparison class is empty. |
298 | * | |
299 | * @note If you have an `Adaptable Binary Function` class or a binary | |
2e01cda6 | 300 | * function type, then you can use the |
3038054c BI |
301 | * @ref indirect_binary_function class, which derives the |
302 | * argument and result types parameter type instead of requiring | |
303 | * you to specify them as template arguments. | |
304 | * | |
305 | * @tparam F A binary functor class, a binary function type, or a pointer to | |
306 | * binary function type. | |
307 | * @param A1 The first argument type. | |
308 | * @param A2 The second argument type. | |
309 | * @param R The result type. | |
310 | * | |
311 | * @see min_max::comparator_base | |
312 | * @see indirect_binary_function | |
313 | * | |
314 | * @ingroup common | |
315 | */ | |
316 | template < typename F | |
317 | , typename A1 | |
318 | , typename A2 | |
319 | , typename R | |
320 | , typename Functor = typename binary_functor<F>::type | |
321 | , bool FunctorIsEmpty = class_is_empty<Functor>::value | |
322 | > | |
323 | class typed_indirect_binary_function : std::binary_function<A1, A2, R> | |
324 | { | |
325 | const F* f; | |
326 | public: | |
327 | /// Constructor captures a pointer to the wrapped function. | |
328 | typed_indirect_binary_function(const F* f) : f(f) {} | |
2e01cda6 | 329 | |
3038054c BI |
330 | /// Return the comparator pointer, or `NULL` if the comparator is stateless. |
331 | const F* pointer() const { return f; } | |
332 | ||
333 | /// Apply the pointed-to functor to the arguments. | |
334 | R operator()(const A1& a1, const A2& a2) const { return (*f)(a1, a2); } | |
335 | }; | |
336 | ||
337 | ||
338 | /// @copydoc typed_indirect_binary_function | |
339 | /// Specialization for an empty functor class. (This is only possible if @a F | |
2e01cda6 | 340 | /// itself is an empty class. If @a F is a function or pointer-to-function |
3038054c BI |
341 | /// type, then the functor will contain a pointer.) |
342 | template <typename F, typename A1, typename A2, typename R, typename Functor> | |
2e01cda6 | 343 | class typed_indirect_binary_function<F, A1, A2, R, Functor, true> : |
3038054c BI |
344 | std::binary_function<A1, A2, R> |
345 | { | |
346 | public: | |
347 | /// Return `NULL` for the comparator pointer of a stateless comparator. | |
348 | const F* pointer() const { return 0; } | |
349 | ||
350 | /// Constructor discards the pointer to a stateless functor class. | |
351 | typed_indirect_binary_function(const F* f) {} | |
2e01cda6 | 352 | |
3038054c BI |
353 | /// Create an instance of the stateless functor class and apply it to the arguments. |
354 | R operator()(const A1& a1, const A2& a2) const { return F()(a1, a2); } | |
355 | }; | |
356 | ||
357 | ||
358 | /** Indirect binary function class with inferred types. | |
359 | * | |
2e01cda6 IV |
360 | * This is identical to @ref cilk::internal::typed_indirect_binary_function, |
361 | * except that it derives the binary function argument and result types from | |
362 | * the parameter type @a F instead of taking them as additional template | |
363 | * parameters. If @a F is a class type, then it must be an `Adaptable Binary | |
364 | * Function`. | |
3038054c BI |
365 | * |
366 | * @see typed_indirect_binary_function | |
367 | * | |
368 | * @ingroup common | |
369 | */ | |
370 | template <typename F, typename Functor = typename binary_functor<F>::type> | |
2e01cda6 | 371 | class indirect_binary_function : |
3038054c BI |
372 | typed_indirect_binary_function< F |
373 | , typename Functor::first_argument_type | |
374 | , typename Functor::second_argument_type | |
375 | , typename Functor::result_type | |
2e01cda6 | 376 | > |
3038054c BI |
377 | { |
378 | typedef typed_indirect_binary_function< F | |
379 | , typename Functor::first_argument_type | |
380 | , typename Functor::second_argument_type | |
381 | , typename Functor::result_type | |
2e01cda6 | 382 | > |
3038054c BI |
383 | base; |
384 | public: | |
385 | indirect_binary_function(const F* f) : base(f) {} ///< Constructor | |
386 | }; | |
387 | ||
388 | ||
389 | /** Choose a type based on a boolean constant. | |
390 | * | |
2e01cda6 | 391 | * This metafunction is identical to C++11's condition metafunction. |
3038054c BI |
392 | * It needs to be here until we can reasonably assume that users will be |
393 | * compiling with C++11. | |
394 | * | |
395 | * @tparam Cond A boolean constant. | |
396 | * @tparam IfTrue A type. | |
397 | * @tparam IfFalse A type. | |
398 | * @result The `type` member will be a typedef of @a IfTrue if @a Cond | |
399 | * is true, and a typedef of @a IfFalse if @a Cond is false. | |
400 | * | |
401 | * @ingroup common | |
402 | */ | |
403 | template <bool Cond, typename IfTrue, typename IfFalse> | |
404 | struct condition | |
405 | { | |
406 | typedef IfTrue type; ///< The type selected by the condition. | |
407 | }; | |
408 | ||
409 | /// @copydoc condition | |
410 | /// Specialization for @a Cond == `false`. | |
411 | template <typename IfTrue, typename IfFalse> | |
412 | struct condition<false, IfTrue, IfFalse> | |
413 | { | |
414 | typedef IfFalse type; ///< The type selected by the condition. | |
415 | }; | |
416 | ||
417 | ||
418 | /** @def __CILKRTS_STATIC_ASSERT | |
419 | * | |
420 | * @brief Compile-time assertion. | |
421 | * | |
422 | * Causes a compilation error if a compile-time constant expression is false. | |
423 | * | |
424 | * @par Usage example. | |
2e01cda6 | 425 | * This assertion is used in reducer_min_max.h to avoid defining |
3038054c BI |
426 | * legacy reducer classes that would not be binary-compatible with the |
427 | * same classes compiled with earlier versions of the reducer library. | |
428 | * | |
429 | * __CILKRTS_STATIC_ASSERT( | |
2e01cda6 | 430 | * internal::class_is_empty< internal::binary_functor<Compare> >::value, |
3038054c BI |
431 | * "cilk::reducer_max<Value, Compare> only works with an empty Compare class"); |
432 | * | |
433 | * @note In a C++11 compiler, this is just the language predefined | |
434 | * `static_assert` macro. | |
435 | * | |
436 | * @note In a non-C++11 compiler, the @a Msg string is not directly included | |
437 | * in the compiler error message, but it may appear if the compiler | |
438 | * prints the source line that the error occurred on. | |
439 | * | |
440 | * @param Cond The expression to test. | |
441 | * @param Msg A string explaining the failure. | |
442 | * | |
443 | * @ingroup common | |
444 | */ | |
445 | #if defined(__INTEL_CXX11_MODE__) || defined(__GXX_EXPERIMENTAL_CXX0X__) | |
446 | # define __CILKRTS_STATIC_ASSERT(Cond, Msg) static_assert(Cond, Msg) | |
447 | #else | |
448 | # define __CILKRTS_STATIC_ASSERT(Cond, Msg) \ | |
449 | typedef int __CILKRTS_STATIC_ASSERT_DUMMY_TYPE \ | |
450 | [::cilk::internal::static_assert_failure<(Cond)>::Success] | |
451 | ||
452 | /// @cond internal | |
453 | template <bool> struct static_assert_failure { }; | |
454 | template <> struct static_assert_failure<true> { enum { Success = 1 }; }; | |
455 | ||
456 | # define __CILKRTS_STATIC_ASSERT_DUMMY_TYPE \ | |
457 | __CILKRTS_STATIC_ASSERT_DUMMY_TYPE1(__cilkrts_static_assert_, __LINE__) | |
458 | # define __CILKRTS_STATIC_ASSERT_DUMMY_TYPE1(a, b) \ | |
459 | __CILKRTS_STATIC_ASSERT_DUMMY_TYPE2(a, b) | |
460 | # define __CILKRTS_STATIC_ASSERT_DUMMY_TYPE2(a, b) a ## b | |
461 | /// @endcond | |
462 | ||
463 | #endif | |
464 | ||
465 | /// @cond internal | |
466 | ||
467 | /** @name Aligned heap management. | |
468 | */ | |
469 | //@{ | |
470 | ||
471 | /** Implementation-specific aligned memory allocation function. | |
472 | * | |
473 | * @param size The minimum number of bytes to allocate. | |
474 | * @param alignment The required alignment (must be a power of 2). | |
475 | * @return The address of a block of memory of at least @a size | |
476 | * bytes. The address will be a multiple of @a alignment. | |
477 | * `NULL` if the allocation fails. | |
478 | * | |
479 | * @see deallocate_aligned() | |
480 | */ | |
481 | inline void* allocate_aligned(std::size_t size, std::size_t alignment) | |
482 | { | |
483 | #ifdef _WIN32 | |
484 | return _aligned_malloc(size, alignment); | |
485 | #else | |
2e01cda6 | 486 | #if defined(__ANDROID__) || defined(__VXWORKS__) |
3038054c BI |
487 | return memalign(std::max(alignment, sizeof(void*)), size); |
488 | #else | |
489 | void* ptr; | |
490 | return (posix_memalign(&ptr, std::max(alignment, sizeof(void*)), size) == 0) ? ptr : 0; | |
491 | #endif | |
2e01cda6 | 492 | #endif |
3038054c BI |
493 | } |
494 | ||
495 | /** Implementation-specific aligned memory deallocation function. | |
496 | * | |
497 | * @param ptr A pointer which was returned by a call to alloc_aligned(). | |
498 | */ | |
499 | inline void deallocate_aligned(void* ptr) | |
500 | { | |
501 | #ifdef _WIN32 | |
502 | _aligned_free(ptr); | |
503 | #else | |
504 | std::free(ptr); | |
2e01cda6 | 505 | #endif |
3038054c BI |
506 | } |
507 | ||
508 | /** Class to allocate and guard an aligned pointer. | |
509 | * | |
510 | * A new_aligned_pointer object allocates aligned heap-allocated memory when | |
2e01cda6 | 511 | * it is created, and automatically deallocates it when it is destroyed |
3038054c BI |
512 | * unless its `ok()` function is called. |
513 | * | |
514 | * @tparam T The type of the object to allocate on the heap. The allocated | |
515 | * will have the size and alignment of an object of type T. | |
516 | */ | |
517 | template <typename T> | |
518 | class new_aligned_pointer { | |
519 | void* m_ptr; | |
520 | public: | |
521 | /// Constructor allocates the pointer. | |
2e01cda6 | 522 | new_aligned_pointer() : |
3038054c BI |
523 | m_ptr(allocate_aligned(sizeof(T), internal::align_of<T>::value)) {} |
524 | /// Destructor deallocates the pointer. | |
525 | ~new_aligned_pointer() { if (m_ptr) deallocate_aligned(m_ptr); } | |
526 | /// Get the pointer. | |
527 | operator void*() { return m_ptr; } | |
528 | /// Return the pointer and release the guard. | |
2e01cda6 | 529 | T* ok() { |
3038054c BI |
530 | T* ptr = static_cast<T*>(m_ptr); |
531 | m_ptr = 0; | |
532 | return ptr; | |
533 | } | |
534 | }; | |
535 | ||
536 | //@} | |
537 | ||
538 | /// @endcond | |
539 | ||
540 | } // namespace internal | |
541 | ||
542 | //@{ | |
543 | ||
544 | /** Allocate an aligned data structure on the heap. | |
545 | * | |
546 | * `cilk::aligned_new<T>([args])` is equivalent to `new T([args])`, except | |
547 | * that it guarantees that the returned pointer will be at least as aligned | |
548 | * as the alignment requirements of type `T`. | |
549 | * | |
550 | * @ingroup common | |
551 | */ | |
552 | template <typename T> | |
553 | T* aligned_new() | |
554 | { | |
555 | internal::new_aligned_pointer<T> ptr; | |
556 | new (ptr) T(); | |
557 | return ptr.ok(); | |
558 | } | |
559 | ||
560 | template <typename T, typename T1> | |
561 | T* aligned_new(const T1& x1) | |
562 | { | |
563 | internal::new_aligned_pointer<T> ptr; | |
564 | new (ptr) T(x1); | |
565 | return ptr.ok(); | |
566 | } | |
567 | ||
568 | template <typename T, typename T1, typename T2> | |
569 | T* aligned_new(const T1& x1, const T2& x2) | |
570 | { | |
571 | internal::new_aligned_pointer<T> ptr; | |
572 | new (ptr) T(x1, x2); | |
573 | return ptr.ok(); | |
574 | } | |
575 | ||
576 | template <typename T, typename T1, typename T2, typename T3> | |
577 | T* aligned_new(const T1& x1, const T2& x2, const T3& x3) | |
578 | { | |
579 | internal::new_aligned_pointer<T> ptr; | |
580 | new (ptr) T(x1, x2, x3); | |
581 | return ptr.ok(); | |
582 | } | |
583 | ||
584 | template <typename T, typename T1, typename T2, typename T3, typename T4> | |
585 | T* aligned_new(const T1& x1, const T2& x2, const T3& x3, const T4& x4) | |
586 | { | |
587 | internal::new_aligned_pointer<T> ptr; | |
588 | new (ptr) T(x1, x2, x3, x4); | |
589 | return ptr.ok(); | |
590 | } | |
591 | ||
592 | template <typename T, typename T1, typename T2, typename T3, typename T4, typename T5> | |
593 | T* aligned_new(const T1& x1, const T2& x2, const T3& x3, const T4& x4, const T5& x5) | |
594 | { | |
595 | internal::new_aligned_pointer<T> ptr; | |
596 | new (ptr) T(x1, x2, x3, x4, x5); | |
597 | return ptr.ok(); | |
598 | } | |
599 | ||
600 | //@} | |
601 | ||
602 | ||
603 | /** Deallocate an aligned data structure on the heap. | |
604 | * | |
605 | * `cilk::aligned_delete(ptr)` is equivalent to `delete ptr`, except that it | |
606 | * operates on a pointer that was allocated by aligned_new(). | |
607 | * | |
608 | * @ingroup common | |
609 | */ | |
610 | template <typename T> | |
611 | void aligned_delete(const T* ptr) | |
612 | { | |
613 | ptr->~T(); | |
614 | internal::deallocate_aligned((void*)ptr); | |
615 | } | |
616 | ||
617 | } // namespace cilk | |
618 | ||
619 | #endif // __cplusplus | |
620 | ||
621 | #endif // METAPROGRAMMING_H_INCLUDED |