Fix for PR other/60644.
[official-gcc.git] / libcilkrts / include / cilk / metaprogramming.h
blob29b0839e788555fc79690b99a16d49c8b74b8f9d
1 /* metaprogramming.h -*- C++ -*-
3 * @copyright
4 * Copyright (C) 2012-2013, Intel Corporation
5 * All rights reserved.
6 *
7 * @copyright
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
12 * * Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * * Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in
16 * the documentation and/or other materials provided with the
17 * distribution.
18 * * Neither the name of Intel Corporation nor the names of its
19 * contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
22 * @copyright
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
28 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
29 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
30 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
31 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
33 * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 * POSSIBILITY OF SUCH DAMAGE.
37 /** @file metaprogramming.h
39 * @brief Defines metaprogramming utility classes used in the Cilk library.
41 * @ingroup common
44 #ifndef METAPROGRAMMING_H_INCLUDED
45 #define METAPROGRAMMING_H_INCLUDED
47 #ifdef __cplusplus
49 #include <functional>
50 #include <new>
51 #include <cstdlib>
52 #ifdef _WIN32
53 #include <malloc.h>
54 #endif
55 #include <algorithm>
57 namespace cilk {
59 namespace internal {
61 /** Test if a class is empty.
63 * If @a Class is an empty (and therefore necessarily stateless) class, then
64 * the “empty base-class optimization” guarantees that
65 * `sizeof(check_for_empty_class<Class>) == sizeof(char)`. Conversely, if
66 * `sizeof(check_for_empty_class<Class>) > sizeof(char)`, then @a Class is not
67 * empty, and we must discriminate distinct instances of @a Class.
69 * Typical usage:
71 * // General definition of A<B> for non-empty B:
72 * template <typename B, bool BIsEmpty = class_is_empty<B>::value> >
73 * class A { ... };
75 * // Specialized definition of A<B> for empty B:
76 * template <typename B>
77 * class A<B, true> { ... };
79 * @tparam Class The class to be tested for emptiness.
81 * @result The `value` member will be `true` if @a Class is empty,
82 * `false` otherwise.
84 * @ingroup common
86 template <class Class>
87 class class_is_empty {
88 class check_for_empty_class : public Class
90 char m_data;
91 public:
92 // Declared but not defined
93 check_for_empty_class();
94 check_for_empty_class(const check_for_empty_class&);
95 check_for_empty_class& operator=(const check_for_empty_class&);
96 ~check_for_empty_class();
98 public:
100 /** Constant is true if and only if @a Class is empty.
102 static const bool value = (sizeof(check_for_empty_class) == sizeof(char));
106 /** Get the alignment of a type.
108 * For example:
110 * align_of<double>::value == 8
112 * @tparam Tp The type whose alignment is to be computed.
114 * @result The `value` member of an instantiation of this class template
115 * will hold the integral alignment requirement of @a Tp.
117 * @pre @a Tp shall be a complete type.
119 * @ingroup common
121 template <typename Tp>
122 struct align_of
124 private:
125 struct imp {
126 char m_padding;
127 Tp m_val;
129 // The following declarations exist to suppress compiler-generated
130 // definitions, in case @a Tp does not have a public default
131 // constructor, copy constructor, or destructor.
132 imp(const imp&); // Declared but not defined
133 ~imp(); // Declared but not defined
136 public:
137 /// The integral alignment requirement of @a Tp.
138 static const std::size_t value = (sizeof(imp) - sizeof(Tp));
142 /** A class containing raw bytes with a specified alignment and size.
144 * An object of type `aligned_storage<S, A>` will have alignment `A` and
145 * size at least `S`. Its contents will be uninitialized bytes.
147 * @tparam Size The required minimum size of the resulting class.
148 * @tparam Alignment The required alignment of the resulting class.
150 * @pre @a Alignment shall be a power of 2 no greater then 64.
152 * @note This is implemented using the `CILK_ALIGNAS` macro, which uses
153 * the non-standard, implementation-specific features
154 * `__declspec(align(N))` on Windows, and
155 * `__attribute__((__aligned__(N)))` on Unix. The `gcc` implementation
156 * of `__attribute__((__aligned__(N)))` requires a numeric literal `N`
157 * (_not_ an arbitrary compile-time constant expression). Therefore,
158 * this class is implemented using specialization on the required
159 * alignment.
161 * @note The template class is specialized only for the supported
162 * alignments. An attempt to instantiate it for an unsupported
163 * alignment will result in a compilation error.
165 template <std::size_t Size, std::size_t Alignment>
166 struct aligned_storage;
168 template<std::size_t Size> class aligned_storage<Size, 1>
169 { CILK_ALIGNAS( 1) char m_bytes[Size]; };
170 template<std::size_t Size> class aligned_storage<Size, 2>
171 { CILK_ALIGNAS( 2) char m_bytes[Size]; };
172 template<std::size_t Size> class aligned_storage<Size, 4>
173 { CILK_ALIGNAS( 4) char m_bytes[Size]; };
174 template<std::size_t Size> class aligned_storage<Size, 8>
175 { CILK_ALIGNAS( 8) char m_bytes[Size]; };
176 template<std::size_t Size> class aligned_storage<Size, 16>
177 { CILK_ALIGNAS(16) char m_bytes[Size]; };
178 template<std::size_t Size> class aligned_storage<Size, 32>
179 { CILK_ALIGNAS(32) char m_bytes[Size]; };
180 template<std::size_t Size> class aligned_storage<Size, 64>
181 { CILK_ALIGNAS(64) char m_bytes[Size]; };
184 /** A buffer of uninitialized bytes with the same size and alignment as a
185 * specified type.
187 * The class `storage_for_object<Type>` will have the same size and alignment
188 * properties as `Type`, but it will contain only raw (uninitialized) bytes.
189 * This allows the definition of a data member which can contain a `Type`
190 * object which is initialized explicitly under program control, rather
191 * than implicitly as part of the initialization of the containing class.
192 * For example:
194 * class C {
195 * storage_for_object<MemberClass> _member;
196 * public:
197 * C() ... // Does NOT initialize _member
198 * void initialize(args)
199 * { new (_member.pointer()) MemberClass(args); }
200 * const MemberClass& member() const { return _member.object(); }
201 * MemberClass& member() { return _member.object(); }
203 * @tparam Type The type whose size and alignment are to be reflected
204 * by this class.
206 template <typename Type>
207 class storage_for_object :
208 aligned_storage< sizeof(Type), align_of<Type>::value >
210 public:
211 /// Return a typed reference to the buffer.
212 const Type& object() const { return *reinterpret_cast<Type*>(this); }
213 Type& object() { return *reinterpret_cast<Type*>(this); }
217 /** Get the functor class corresponding to a binary function type.
219 * The `binary_functor` template class class can be instantiated with a binary
220 * functor class or with a real binary function, and will yield an equivalent
221 * binary functor class class in either case.
223 * @tparam F A binary functor class, a binary function type, or a pointer to
224 * binary function type.
226 * @result `binary_functor<F>::%type` will be the same as @a F if @a F is
227 * a class. It will be a `std::pointer_to_binary_function` wrapper
228 * if @a F is a binary function or binary function pointer type.
229 * (It will _not_ necessarily be an `Adaptable Binary Function`
230 * class, since @a F might be a non-adaptable binary functor
231 * class.)
233 * @ingroup common
235 template <typename F>
236 struct binary_functor {
237 /// The binary functor class equivalent to @a F.
238 typedef F type;
241 /// @copydoc binary_functor
242 /// Specialization for binary function.
243 template <typename R, typename A, typename B>
244 struct binary_functor<R(A,B)> {
245 /// The binary functor class equivalent to @a F.
246 typedef std::pointer_to_binary_function<A, B, R> type;
249 /// @copydoc binary_functor
250 /// Specialization for pointer to binary function.
251 template <typename R, typename A, typename B>
252 struct binary_functor<R(*)(A,B)> {
253 /// The binary functor class equivalent to @a F.
254 typedef std::pointer_to_binary_function<A, B, R> type;
258 /** Indirect binary function class with specified types.
260 * `typed_indirect_binary_function<F>` is an `Adaptable Binary Function` class
261 * based on an existing binary functor class or binary function type @a F. If
262 * @a F is a stateless class, then this class will be empty, and its
263 * `operator()` will invoke @a F’s `operator()`. Otherwise, an object of this
264 * class will hold a pointer to an object of type @a F, and will refer its
265 * `operator()` calls to the pointed-to @a F object.
267 * That is, suppose that we have the declarations:
269 * F *p;
270 * typed_indirect_binary_function<F, int, int, bool> ibf(p);
272 * Then:
274 * - `ibf(x, y) == (*p)(x, y)`.
275 * - `ibf(x, y)` will not do a pointer dereference if `F` is an empty class.
277 * @note Just to repeat: if `F` is an empty class, then
278 * `typed_indirect_binary_function\<F\>' is also an empty class.
279 * This is critical for its use in the @ref min_max::view_base
280 * "min/max reducer view classes", where it allows the view to
281 * call a comparison functor in the monoid without actually
282 * having to allocate a pointer in the view class when the
283 * comparison class is empty.
285 * @note If you have an `Adaptable Binary Function` class or a binary
286 * function type, then you can use the
287 * @ref indirect_binary_function class, which derives the
288 * argument and result types parameter type instead of requiring
289 * you to specify them as template arguments.
291 * @tparam F A binary functor class, a binary function type, or a pointer to
292 * binary function type.
293 * @param A1 The first argument type.
294 * @param A2 The second argument type.
295 * @param R The result type.
297 * @see min_max::comparator_base
298 * @see indirect_binary_function
300 * @ingroup common
302 template < typename F
303 , typename A1
304 , typename A2
305 , typename R
306 , typename Functor = typename binary_functor<F>::type
307 , bool FunctorIsEmpty = class_is_empty<Functor>::value
309 class typed_indirect_binary_function : std::binary_function<A1, A2, R>
311 const F* f;
312 public:
313 /// Constructor captures a pointer to the wrapped function.
314 typed_indirect_binary_function(const F* f) : f(f) {}
316 /// Return the comparator pointer, or `NULL` if the comparator is stateless.
317 const F* pointer() const { return f; }
319 /// Apply the pointed-to functor to the arguments.
320 R operator()(const A1& a1, const A2& a2) const { return (*f)(a1, a2); }
324 /// @copydoc typed_indirect_binary_function
325 /// Specialization for an empty functor class. (This is only possible if @a F
326 /// itself is an empty class. If @a F is a function or pointer-to-function
327 /// type, then the functor will contain a pointer.)
328 template <typename F, typename A1, typename A2, typename R, typename Functor>
329 class typed_indirect_binary_function<F, A1, A2, R, Functor, true> :
330 std::binary_function<A1, A2, R>
332 public:
333 /// Return `NULL` for the comparator pointer of a stateless comparator.
334 const F* pointer() const { return 0; }
336 /// Constructor discards the pointer to a stateless functor class.
337 typed_indirect_binary_function(const F* f) {}
339 /// Create an instance of the stateless functor class and apply it to the arguments.
340 R operator()(const A1& a1, const A2& a2) const { return F()(a1, a2); }
344 /** Indirect binary function class with inferred types.
346 * This is identical to @ref typed_indirect_binary_function, except that it
347 * derives the binary function argument and result types from the parameter
348 * type @a F instead of taking them as additional template parameters. If @a F
349 * is a class type, then it must be an `Adaptable Binary Function`.
351 * @see typed_indirect_binary_function
353 * @ingroup common
355 template <typename F, typename Functor = typename binary_functor<F>::type>
356 class indirect_binary_function :
357 typed_indirect_binary_function< F
358 , typename Functor::first_argument_type
359 , typename Functor::second_argument_type
360 , typename Functor::result_type
363 typedef typed_indirect_binary_function< F
364 , typename Functor::first_argument_type
365 , typename Functor::second_argument_type
366 , typename Functor::result_type
368 base;
369 public:
370 indirect_binary_function(const F* f) : base(f) {} ///< Constructor
374 /** Choose a type based on a boolean constant.
376 * This metafunction is identical to C++11’s condition metafunction.
377 * It needs to be here until we can reasonably assume that users will be
378 * compiling with C++11.
380 * @tparam Cond A boolean constant.
381 * @tparam IfTrue A type.
382 * @tparam IfFalse A type.
383 * @result The `type` member will be a typedef of @a IfTrue if @a Cond
384 * is true, and a typedef of @a IfFalse if @a Cond is false.
386 * @ingroup common
388 template <bool Cond, typename IfTrue, typename IfFalse>
389 struct condition
391 typedef IfTrue type; ///< The type selected by the condition.
394 /// @copydoc condition
395 /// Specialization for @a Cond == `false`.
396 template <typename IfTrue, typename IfFalse>
397 struct condition<false, IfTrue, IfFalse>
399 typedef IfFalse type; ///< The type selected by the condition.
403 /** @def __CILKRTS_STATIC_ASSERT
405 * @brief Compile-time assertion.
407 * Causes a compilation error if a compile-time constant expression is false.
409 * @par Usage example.
410 * This assertion is used in reducer_min_max.h to avoid defining
411 * legacy reducer classes that would not be binary-compatible with the
412 * same classes compiled with earlier versions of the reducer library.
414 * __CILKRTS_STATIC_ASSERT(
415 * internal::class_is_empty< internal::binary_functor<Compare> >::value,
416 * "cilk::reducer_max<Value, Compare> only works with an empty Compare class");
418 * @note In a C++11 compiler, this is just the language predefined
419 * `static_assert` macro.
421 * @note In a non-C++11 compiler, the @a Msg string is not directly included
422 * in the compiler error message, but it may appear if the compiler
423 * prints the source line that the error occurred on.
425 * @param Cond The expression to test.
426 * @param Msg A string explaining the failure.
428 * @ingroup common
430 #if defined(__INTEL_CXX11_MODE__) || defined(__GXX_EXPERIMENTAL_CXX0X__)
431 # define __CILKRTS_STATIC_ASSERT(Cond, Msg) static_assert(Cond, Msg)
432 #else
433 # define __CILKRTS_STATIC_ASSERT(Cond, Msg) \
434 typedef int __CILKRTS_STATIC_ASSERT_DUMMY_TYPE \
435 [::cilk::internal::static_assert_failure<(Cond)>::Success]
437 /// @cond internal
438 template <bool> struct static_assert_failure { };
439 template <> struct static_assert_failure<true> { enum { Success = 1 }; };
441 # define __CILKRTS_STATIC_ASSERT_DUMMY_TYPE \
442 __CILKRTS_STATIC_ASSERT_DUMMY_TYPE1(__cilkrts_static_assert_, __LINE__)
443 # define __CILKRTS_STATIC_ASSERT_DUMMY_TYPE1(a, b) \
444 __CILKRTS_STATIC_ASSERT_DUMMY_TYPE2(a, b)
445 # define __CILKRTS_STATIC_ASSERT_DUMMY_TYPE2(a, b) a ## b
446 /// @endcond
448 #endif
450 /// @cond internal
452 /** @name Aligned heap management.
454 //@{
456 /** Implementation-specific aligned memory allocation function.
458 * @param size The minimum number of bytes to allocate.
459 * @param alignment The required alignment (must be a power of 2).
460 * @return The address of a block of memory of at least @a size
461 * bytes. The address will be a multiple of @a alignment.
462 * `NULL` if the allocation fails.
464 * @see deallocate_aligned()
466 inline void* allocate_aligned(std::size_t size, std::size_t alignment)
468 #ifdef _WIN32
469 return _aligned_malloc(size, alignment);
470 #else
471 #if defined(__ANDROID__)
472 return memalign(std::max(alignment, sizeof(void*)), size);
473 #else
474 void* ptr;
475 return (posix_memalign(&ptr, std::max(alignment, sizeof(void*)), size) == 0) ? ptr : 0;
476 #endif
477 #endif
480 /** Implementation-specific aligned memory deallocation function.
482 * @param ptr A pointer which was returned by a call to alloc_aligned().
484 inline void deallocate_aligned(void* ptr)
486 #ifdef _WIN32
487 _aligned_free(ptr);
488 #else
489 std::free(ptr);
490 #endif
493 /** Class to allocate and guard an aligned pointer.
495 * A new_aligned_pointer object allocates aligned heap-allocated memory when
496 * it is created, and automatically deallocates it when it is destroyed
497 * unless its `ok()` function is called.
499 * @tparam T The type of the object to allocate on the heap. The allocated
500 * will have the size and alignment of an object of type T.
502 template <typename T>
503 class new_aligned_pointer {
504 void* m_ptr;
505 public:
506 /// Constructor allocates the pointer.
507 new_aligned_pointer() :
508 m_ptr(allocate_aligned(sizeof(T), internal::align_of<T>::value)) {}
509 /// Destructor deallocates the pointer.
510 ~new_aligned_pointer() { if (m_ptr) deallocate_aligned(m_ptr); }
511 /// Get the pointer.
512 operator void*() { return m_ptr; }
513 /// Return the pointer and release the guard.
514 T* ok() {
515 T* ptr = static_cast<T*>(m_ptr);
516 m_ptr = 0;
517 return ptr;
521 //@}
523 /// @endcond
525 } // namespace internal
527 //@{
529 /** Allocate an aligned data structure on the heap.
531 * `cilk::aligned_new<T>([args])` is equivalent to `new T([args])`, except
532 * that it guarantees that the returned pointer will be at least as aligned
533 * as the alignment requirements of type `T`.
535 * @ingroup common
537 template <typename T>
538 T* aligned_new()
540 internal::new_aligned_pointer<T> ptr;
541 new (ptr) T();
542 return ptr.ok();
545 template <typename T, typename T1>
546 T* aligned_new(const T1& x1)
548 internal::new_aligned_pointer<T> ptr;
549 new (ptr) T(x1);
550 return ptr.ok();
553 template <typename T, typename T1, typename T2>
554 T* aligned_new(const T1& x1, const T2& x2)
556 internal::new_aligned_pointer<T> ptr;
557 new (ptr) T(x1, x2);
558 return ptr.ok();
561 template <typename T, typename T1, typename T2, typename T3>
562 T* aligned_new(const T1& x1, const T2& x2, const T3& x3)
564 internal::new_aligned_pointer<T> ptr;
565 new (ptr) T(x1, x2, x3);
566 return ptr.ok();
569 template <typename T, typename T1, typename T2, typename T3, typename T4>
570 T* aligned_new(const T1& x1, const T2& x2, const T3& x3, const T4& x4)
572 internal::new_aligned_pointer<T> ptr;
573 new (ptr) T(x1, x2, x3, x4);
574 return ptr.ok();
577 template <typename T, typename T1, typename T2, typename T3, typename T4, typename T5>
578 T* aligned_new(const T1& x1, const T2& x2, const T3& x3, const T4& x4, const T5& x5)
580 internal::new_aligned_pointer<T> ptr;
581 new (ptr) T(x1, x2, x3, x4, x5);
582 return ptr.ok();
585 //@}
588 /** Deallocate an aligned data structure on the heap.
590 * `cilk::aligned_delete(ptr)` is equivalent to `delete ptr`, except that it
591 * operates on a pointer that was allocated by aligned_new().
593 * @ingroup common
595 template <typename T>
596 void aligned_delete(const T* ptr)
598 ptr->~T();
599 internal::deallocate_aligned((void*)ptr);
602 } // namespace cilk
604 #endif // __cplusplus
606 #endif // METAPROGRAMMING_H_INCLUDED