summaryrefslogtreecommitdiff
path: root/libcilkrts/include/cilk/metaprogramming.h
diff options
context:
space:
mode:
Diffstat (limited to 'libcilkrts/include/cilk/metaprogramming.h')
-rw-r--r--libcilkrts/include/cilk/metaprogramming.h621
1 files changed, 0 insertions, 621 deletions
diff --git a/libcilkrts/include/cilk/metaprogramming.h b/libcilkrts/include/cilk/metaprogramming.h
deleted file mode 100644
index 2df7cf6467c..00000000000
--- a/libcilkrts/include/cilk/metaprogramming.h
+++ /dev/null
@@ -1,621 +0,0 @@
-/* metaprogramming.h -*- C++ -*-
- *
- * Copyright (C) 2012-2016, Intel Corporation
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
- * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- *
- * *********************************************************************
- *
- * PLEASE NOTE: This file is a downstream copy of a file mainitained in
- * a repository at cilkplus.org. Changes made to this file that are not
- * submitted through the contribution process detailed at
- * http://www.cilkplus.org/submit-cilk-contribution will be lost the next
- * time that a new version is released. Changes only submitted to the
- * GNU compiler collection or posted to the git repository at
- * https://bitbucket.org/intelcilkruntime/intel-cilk-runtime.git are
- * not tracked.
- *
- * We welcome your contributions to this open source project. Thank you
- * for your assistance in helping us improve Cilk Plus.
- */
-
-/** @file metaprogramming.h
- *
- * @brief Defines metaprogramming utility classes used in the Intel(R) Cilk(TM) Plus library.
- *
- * @ingroup common
- */
-
-#ifndef METAPROGRAMMING_H_INCLUDED
-#define METAPROGRAMMING_H_INCLUDED
-
-#ifdef __cplusplus
-
-#include <functional>
-#include <new>
-#include <cstdlib>
-#ifdef _WIN32
-#include <malloc.h>
-#endif
-#include <algorithm>
-
-namespace cilk {
-
-namespace internal {
-
-/** Test if a class is empty.
- *
- * If @a Class is an empty (and therefore necessarily stateless) class, then
- * the "empty base-class optimization" guarantees that
- * `sizeof(check_for_empty_class<Class>) == sizeof(char)`. Conversely, if
- * `sizeof(check_for_empty_class<Class>) > sizeof(char)`, then @a Class is not
- * empty, and we must discriminate distinct instances of @a Class.
- *
- * Typical usage:
- *
- * // General definition of A<B> for non-empty B:
- * template <typename B, bool BIsEmpty = class_is_empty<B>::value> >
- * class A { ... };
- *
- * // Specialized definition of A<B> for empty B:
- * template <typename B>
- * class A<B, true> { ... };
- *
- * @tparam Class The class to be tested for emptiness.
- *
- * @result The `value` member will be `true` if @a Class is empty,
- * `false` otherwise.
- *
- * @ingroup common
- */
-template <class Class>
-class class_is_empty {
- class check_for_empty_class : public Class
- {
- char m_data;
- public:
- // Declared but not defined
- check_for_empty_class();
- check_for_empty_class(const check_for_empty_class&);
- check_for_empty_class& operator=(const check_for_empty_class&);
- ~check_for_empty_class();
- };
-public:
-
- /** Constant is true if and only if @a Class is empty.
- */
- static const bool value = (sizeof(check_for_empty_class) == sizeof(char));
-};
-
-
-/** Get the alignment of a type.
- *
- * For example:
- *
- * align_of<double>::value == 8
- *
- * @tparam Tp The type whose alignment is to be computed.
- *
- * @result The `value` member of an instantiation of this class template
- * will hold the integral alignment requirement of @a Tp.
- *
- * @pre @a Tp shall be a complete type.
- *
- * @ingroup common
- */
-template <typename Tp>
-struct align_of
-{
-private:
- struct imp {
- char m_padding;
- Tp m_val;
-
- // The following declarations exist to suppress compiler-generated
- // definitions, in case @a Tp does not have a public default
- // constructor, copy constructor, or destructor.
- imp(const imp&); // Declared but not defined
- ~imp(); // Declared but not defined
- };
-
-public:
- /// The integral alignment requirement of @a Tp.
- static const std::size_t value = (sizeof(imp) - sizeof(Tp));
-};
-
-
-/** A class containing raw bytes with a specified alignment and size.
- *
- * An object of type `aligned_storage<S, A>` will have alignment `A` and
- * size at least `S`. Its contents will be uninitialized bytes.
- *
- * @tparam Size The required minimum size of the resulting class.
- * @tparam Alignment The required alignment of the resulting class.
- *
- * @pre @a Alignment shall be a power of 2 no greater than 64.
- *
- * @note This is implemented using the `CILK_ALIGNAS` macro, which uses
- * the non-standard, implementation-specific features
- * `__declspec(align(N))` on Windows, and
- * `__attribute__((__aligned__(N)))` on Unix. The `gcc` implementation
- * of `__attribute__((__aligned__(N)))` requires a numeric literal `N`
- * (_not_ an arbitrary compile-time constant expression). Therefore,
- * this class is implemented using specialization on the required
- * alignment.
- *
- * @note The template class is specialized only for the supported
- * alignments. An attempt to instantiate it for an unsupported
- * alignment will result in a compilation error.
- */
-template <std::size_t Size, std::size_t Alignment>
-struct aligned_storage;
-
-/// @cond
-template<std::size_t Size> class aligned_storage<Size, 1>
- { CILK_ALIGNAS( 1) char m_bytes[Size]; };
-template<std::size_t Size> class aligned_storage<Size, 2>
- { CILK_ALIGNAS( 2) char m_bytes[Size]; };
-template<std::size_t Size> class aligned_storage<Size, 4>
- { CILK_ALIGNAS( 4) char m_bytes[Size]; };
-template<std::size_t Size> class aligned_storage<Size, 8>
- { CILK_ALIGNAS( 8) char m_bytes[Size]; };
-template<std::size_t Size> class aligned_storage<Size, 16>
- { CILK_ALIGNAS(16) char m_bytes[Size]; };
-template<std::size_t Size> class aligned_storage<Size, 32>
- { CILK_ALIGNAS(32) char m_bytes[Size]; };
-template<std::size_t Size> class aligned_storage<Size, 64>
- { CILK_ALIGNAS(64) char m_bytes[Size]; };
-/// @endcond
-
-/** A buffer of uninitialized bytes with the same size and alignment as a
- * specified type.
- *
- * The class `storage_for_object<Type>` will have the same size and alignment
- * properties as `Type`, but it will contain only raw (uninitialized) bytes.
- * This allows the definition of a data member which can contain a `Type`
- * object which is initialized explicitly under program control, rather
- * than implicitly as part of the initialization of the containing class.
- * For example:
- *
- * class C {
- * storage_for_object<MemberClass> _member;
- * public:
- * C() ... // Does NOT initialize _member
- * void initialize(args)
- * { new (_member.pointer()) MemberClass(args); }
- * const MemberClass& member() const { return _member.object(); }
- * MemberClass& member() { return _member.object(); }
- *
- * @tparam Type The type whose size and alignment are to be reflected
- * by this class.
- */
-template <typename Type>
-class storage_for_object :
- aligned_storage< sizeof(Type), align_of<Type>::value >
-{
-public:
- /// Return a typed reference to the buffer.
- const Type& object() const { return *reinterpret_cast<Type*>(this); }
- /// Return a typed reference to the buffer.
- Type& object() { return *reinterpret_cast<Type*>(this); }
-};
-
-
-/** Get the functor class corresponding to a binary function type.
- *
- * The `binary_functor` template class can be instantiated with a binary
- * functor class or with a real binary function, and will yield an equivalent
- * binary functor class in either case.
- *
- * @tparam F A binary functor class, a binary function type, or a pointer to
- * binary function type.
- *
- * @result `binary_functor<F>::%type` will be the same as @a F if @a F is
- * a class. It will be a `std::pointer_to_binary_function` wrapper
- * if @a F is a binary function or binary function pointer type.
- * (It will _not_ necessarily be an `Adaptable Binary Function`
- * class, since @a F might be a non-adaptable binary functor
- * class.)
- *
- * @ingroup common
- */
-template <typename F>
-struct binary_functor {
- /// The binary functor class equivalent to @a F.
- typedef F type;
-};
-
-/// @copydoc binary_functor
-/// Specialization for binary function.
-template <typename R, typename A, typename B>
-struct binary_functor<R(A,B)> {
- /// The binary functor class equivalent to @a F.
- typedef std::pointer_to_binary_function<A, B, R> type;
-};
-
-/// @copydoc binary_functor
-/// Specialization for pointer to binary function.
-template <typename R, typename A, typename B>
-struct binary_functor<R(*)(A,B)> {
- /// The binary functor class equivalent to @a F.
- typedef std::pointer_to_binary_function<A, B, R> type;
-};
-
-
-/** Indirect binary function class with specified types.
- *
- * `typed_indirect_binary_function<F>` is an `Adaptable Binary Function` class
- * based on an existing binary functor class or binary function type @a F. If
- * @a F is a stateless class, then this class will be empty, and its
- * `operator()` will invoke @a F's `operator()`. Otherwise, an object of this
- * class will hold a pointer to an object of type @a F, and will refer its
- * `operator()` calls to the pointed-to @a F object.
- *
- * That is, suppose that we have the declarations:
- *
- * F *p;
- * typed_indirect_binary_function<F, int, int, bool> ibf(p);
- *
- * Then:
- *
- * - `ibf(x, y) == (*p)(x, y)`.
- * - `ibf(x, y)` will not do a pointer dereference if `F` is an empty class.
- *
- * @note Just to repeat: if `F` is an empty class, then
- * `typed_indirect_binary_function\<F\>' is also an empty class.
- * This is critical for its use in the
- * @ref cilk::cilk_lib_1_1::min_max_internal::view_base
- * "min/max reducer view classes", where it allows the view to
- * call a comparison functor in the monoid without actually
- * having to allocate a pointer in the view class when the
- * comparison class is empty.
- *
- * @note If you have an `Adaptable Binary Function` class or a binary
- * function type, then you can use the
- * @ref indirect_binary_function class, which derives the
- * argument and result types parameter type instead of requiring
- * you to specify them as template arguments.
- *
- * @tparam F A binary functor class, a binary function type, or a pointer to
- * binary function type.
- * @param A1 The first argument type.
- * @param A2 The second argument type.
- * @param R The result type.
- *
- * @see min_max::comparator_base
- * @see indirect_binary_function
- *
- * @ingroup common
- */
-template < typename F
- , typename A1
- , typename A2
- , typename R
- , typename Functor = typename binary_functor<F>::type
- , bool FunctorIsEmpty = class_is_empty<Functor>::value
- >
-class typed_indirect_binary_function : std::binary_function<A1, A2, R>
-{
- const F* f;
-public:
- /// Constructor captures a pointer to the wrapped function.
- typed_indirect_binary_function(const F* f) : f(f) {}
-
- /// Return the comparator pointer, or `NULL` if the comparator is stateless.
- const F* pointer() const { return f; }
-
- /// Apply the pointed-to functor to the arguments.
- R operator()(const A1& a1, const A2& a2) const { return (*f)(a1, a2); }
-};
-
-
-/// @copydoc typed_indirect_binary_function
-/// Specialization for an empty functor class. (This is only possible if @a F
-/// itself is an empty class. If @a F is a function or pointer-to-function
-/// type, then the functor will contain a pointer.)
-template <typename F, typename A1, typename A2, typename R, typename Functor>
-class typed_indirect_binary_function<F, A1, A2, R, Functor, true> :
- std::binary_function<A1, A2, R>
-{
-public:
- /// Return `NULL` for the comparator pointer of a stateless comparator.
- const F* pointer() const { return 0; }
-
- /// Constructor discards the pointer to a stateless functor class.
- typed_indirect_binary_function(const F* f) {}
-
- /// Create an instance of the stateless functor class and apply it to the arguments.
- R operator()(const A1& a1, const A2& a2) const { return F()(a1, a2); }
-};
-
-
-/** Indirect binary function class with inferred types.
- *
- * This is identical to @ref cilk::internal::typed_indirect_binary_function,
- * except that it derives the binary function argument and result types from
- * the parameter type @a F instead of taking them as additional template
- * parameters. If @a F is a class type, then it must be an `Adaptable Binary
- * Function`.
- *
- * @see typed_indirect_binary_function
- *
- * @ingroup common
- */
-template <typename F, typename Functor = typename binary_functor<F>::type>
-class indirect_binary_function :
- typed_indirect_binary_function< F
- , typename Functor::first_argument_type
- , typename Functor::second_argument_type
- , typename Functor::result_type
- >
-{
- typedef typed_indirect_binary_function< F
- , typename Functor::first_argument_type
- , typename Functor::second_argument_type
- , typename Functor::result_type
- >
- base;
-public:
- indirect_binary_function(const F* f) : base(f) {} ///< Constructor
-};
-
-
-/** Choose a type based on a boolean constant.
- *
- * This metafunction is identical to C++11's condition metafunction.
- * It needs to be here until we can reasonably assume that users will be
- * compiling with C++11.
- *
- * @tparam Cond A boolean constant.
- * @tparam IfTrue A type.
- * @tparam IfFalse A type.
- * @result The `type` member will be a typedef of @a IfTrue if @a Cond
- * is true, and a typedef of @a IfFalse if @a Cond is false.
- *
- * @ingroup common
- */
-template <bool Cond, typename IfTrue, typename IfFalse>
-struct condition
-{
- typedef IfTrue type; ///< The type selected by the condition.
-};
-
-/// @copydoc condition
-/// Specialization for @a Cond == `false`.
-template <typename IfTrue, typename IfFalse>
-struct condition<false, IfTrue, IfFalse>
-{
- typedef IfFalse type; ///< The type selected by the condition.
-};
-
-
-/** @def __CILKRTS_STATIC_ASSERT
- *
- * @brief Compile-time assertion.
- *
- * Causes a compilation error if a compile-time constant expression is false.
- *
- * @par Usage example.
- * This assertion is used in reducer_min_max.h to avoid defining
- * legacy reducer classes that would not be binary-compatible with the
- * same classes compiled with earlier versions of the reducer library.
- *
- * __CILKRTS_STATIC_ASSERT(
- * internal::class_is_empty< internal::binary_functor<Compare> >::value,
- * "cilk::reducer_max<Value, Compare> only works with an empty Compare class");
- *
- * @note In a C++11 compiler, this is just the language predefined
- * `static_assert` macro.
- *
- * @note In a non-C++11 compiler, the @a Msg string is not directly included
- * in the compiler error message, but it may appear if the compiler
- * prints the source line that the error occurred on.
- *
- * @param Cond The expression to test.
- * @param Msg A string explaining the failure.
- *
- * @ingroup common
- */
-#if defined(__INTEL_CXX11_MODE__) || defined(__GXX_EXPERIMENTAL_CXX0X__)
-# define __CILKRTS_STATIC_ASSERT(Cond, Msg) static_assert(Cond, Msg)
-#else
-# define __CILKRTS_STATIC_ASSERT(Cond, Msg) \
- typedef int __CILKRTS_STATIC_ASSERT_DUMMY_TYPE \
- [::cilk::internal::static_assert_failure<(Cond)>::Success]
-
-/// @cond internal
- template <bool> struct static_assert_failure { };
- template <> struct static_assert_failure<true> { enum { Success = 1 }; };
-
-# define __CILKRTS_STATIC_ASSERT_DUMMY_TYPE \
- __CILKRTS_STATIC_ASSERT_DUMMY_TYPE1(__cilkrts_static_assert_, __LINE__)
-# define __CILKRTS_STATIC_ASSERT_DUMMY_TYPE1(a, b) \
- __CILKRTS_STATIC_ASSERT_DUMMY_TYPE2(a, b)
-# define __CILKRTS_STATIC_ASSERT_DUMMY_TYPE2(a, b) a ## b
-/// @endcond
-
-#endif
-
-/// @cond internal
-
-/** @name Aligned heap management.
- */
-//@{
-
-/** Implementation-specific aligned memory allocation function.
- *
- * @param size The minimum number of bytes to allocate.
- * @param alignment The required alignment (must be a power of 2).
- * @return The address of a block of memory of at least @a size
- * bytes. The address will be a multiple of @a alignment.
- * `NULL` if the allocation fails.
- *
- * @see deallocate_aligned()
- */
-inline void* allocate_aligned(std::size_t size, std::size_t alignment)
-{
-#ifdef _WIN32
- return _aligned_malloc(size, alignment);
-#else
-#if defined(__ANDROID__) || defined(__VXWORKS__)
- return memalign(std::max(alignment, sizeof(void*)), size);
-#else
- void* ptr;
- return (posix_memalign(&ptr, std::max(alignment, sizeof(void*)), size) == 0) ? ptr : 0;
-#endif
-#endif
-}
-
-/** Implementation-specific aligned memory deallocation function.
- *
- * @param ptr A pointer which was returned by a call to alloc_aligned().
- */
-inline void deallocate_aligned(void* ptr)
-{
-#ifdef _WIN32
- _aligned_free(ptr);
-#else
- std::free(ptr);
-#endif
-}
-
-/** Class to allocate and guard an aligned pointer.
- *
- * A new_aligned_pointer object allocates aligned heap-allocated memory when
- * it is created, and automatically deallocates it when it is destroyed
- * unless its `ok()` function is called.
- *
- * @tparam T The type of the object to allocate on the heap. The allocated
- * will have the size and alignment of an object of type T.
- */
-template <typename T>
-class new_aligned_pointer {
- void* m_ptr;
-public:
- /// Constructor allocates the pointer.
- new_aligned_pointer() :
- m_ptr(allocate_aligned(sizeof(T), internal::align_of<T>::value)) {}
- /// Destructor deallocates the pointer.
- ~new_aligned_pointer() { if (m_ptr) deallocate_aligned(m_ptr); }
- /// Get the pointer.
- operator void*() { return m_ptr; }
- /// Return the pointer and release the guard.
- T* ok() {
- T* ptr = static_cast<T*>(m_ptr);
- m_ptr = 0;
- return ptr;
- }
-};
-
-//@}
-
-/// @endcond
-
-} // namespace internal
-
-//@{
-
-/** Allocate an aligned data structure on the heap.
- *
- * `cilk::aligned_new<T>([args])` is equivalent to `new T([args])`, except
- * that it guarantees that the returned pointer will be at least as aligned
- * as the alignment requirements of type `T`.
- *
- * @ingroup common
- */
-template <typename T>
-T* aligned_new()
-{
- internal::new_aligned_pointer<T> ptr;
- new (ptr) T();
- return ptr.ok();
-}
-
-template <typename T, typename T1>
-T* aligned_new(const T1& x1)
-{
- internal::new_aligned_pointer<T> ptr;
- new (ptr) T(x1);
- return ptr.ok();
-}
-
-template <typename T, typename T1, typename T2>
-T* aligned_new(const T1& x1, const T2& x2)
-{
- internal::new_aligned_pointer<T> ptr;
- new (ptr) T(x1, x2);
- return ptr.ok();
-}
-
-template <typename T, typename T1, typename T2, typename T3>
-T* aligned_new(const T1& x1, const T2& x2, const T3& x3)
-{
- internal::new_aligned_pointer<T> ptr;
- new (ptr) T(x1, x2, x3);
- return ptr.ok();
-}
-
-template <typename T, typename T1, typename T2, typename T3, typename T4>
-T* aligned_new(const T1& x1, const T2& x2, const T3& x3, const T4& x4)
-{
- internal::new_aligned_pointer<T> ptr;
- new (ptr) T(x1, x2, x3, x4);
- return ptr.ok();
-}
-
-template <typename T, typename T1, typename T2, typename T3, typename T4, typename T5>
-T* aligned_new(const T1& x1, const T2& x2, const T3& x3, const T4& x4, const T5& x5)
-{
- internal::new_aligned_pointer<T> ptr;
- new (ptr) T(x1, x2, x3, x4, x5);
- return ptr.ok();
-}
-
-//@}
-
-
-/** Deallocate an aligned data structure on the heap.
- *
- * `cilk::aligned_delete(ptr)` is equivalent to `delete ptr`, except that it
- * operates on a pointer that was allocated by aligned_new().
- *
- * @ingroup common
- */
-template <typename T>
-void aligned_delete(const T* ptr)
-{
- ptr->~T();
- internal::deallocate_aligned((void*)ptr);
-}
-
-} // namespace cilk
-
-#endif // __cplusplus
-
-#endif // METAPROGRAMMING_H_INCLUDED