1 /*  metaprogramming.h                  -*- C++ -*-
2  *
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:
11  *
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.
21  *
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.
35  */
36 
37 /** @file metaprogramming.h
38  *
39  *  @brief Defines metaprogramming utility classes used in the Cilk library.
40  *
41  *  @ingroup common
42  */
43 
44 #ifndef METAPROGRAMMING_H_INCLUDED
45 #define METAPROGRAMMING_H_INCLUDED
46 
47 #ifdef __cplusplus
48 
49 #include <functional>
50 #include <new>
51 #include <cstdlib>
52 #ifdef _WIN32
53 #include <malloc.h>
54 #endif
55 #include <algorithm>
56 
57 namespace cilk {
58 
59 namespace internal {
60 
61 /** Test if a class is empty.
62  *
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.
68  *
69  *  Typical usage:
70  *
71  *      // General definition of A<B> for non-empty B:
72  *      template <typename B, bool BIsEmpty = class_is_empty<B>::value> >
73  *      class A { ... };
74  *
75  *      // Specialized definition of A<B> for empty B:
76  *      template <typename B>
77  *      class A<B, true> { ... };
78  *
79  *  @tparam Class   The class to be tested for emptiness.
80  *
81  *  @result         The `value` member will be `true` if @a Class is empty,
82  *                  `false` otherwise.
83  *
84  *  @ingroup common
85  */
86 template <class Class>
87 class class_is_empty {
88     class check_for_empty_class : public Class
89     {
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();
97     };
98 public:
99 
100     /** Constant is true if and only if @a Class is empty.
101      */
102     static const bool value = (sizeof(check_for_empty_class) == sizeof(char));
103 };
104 
105 
106 /** Get the alignment of a type.
107  *
108  *  For example:
109  *
110  *      align_of<double>::value == 8
111  *
112  *  @tparam Tp  The type whose alignment is to be computed.
113  *
114  *  @result     The `value` member of an instantiation of this class template
115  *              will hold the integral alignment requirement of @a Tp.
116  *
117  *  @pre        @a Tp shall be a complete type.
118  *
119  *  @ingroup common
120  */
121 template <typename Tp>
122 struct align_of
123 {
124 private:
125     struct imp {
126         char m_padding;
127         Tp   m_val;
128 
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
134     };
135 
136 public:
137     /// The integral alignment requirement of @a Tp.
138     static const std::size_t    value = (sizeof(imp) - sizeof(Tp));
139 };
140 
141 
142 /** A class containing raw bytes with a specified alignment and size.
143  *
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.
146  *
147  *  @tparam Size        The required minimum size of the resulting class.
148  *  @tparam Alignment   The required alignment of the resulting class.
149  *
150  *  @pre    @a Alignment shall be a power of 2 no greater then 64.
151  *
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.
160  *
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.
164  */
165 template <std::size_t Size, std::size_t Alignment>
166 struct aligned_storage;
167 
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]; };
182 
183 
184 /** A buffer of uninitialized bytes with the same size and alignment as a
185  *  specified type.
186  *
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:
193  *
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(); }
202  *
203  *  @tparam Type    The type whose size and alignment are to be reflected
204  *                  by this class.
205  */
206 template <typename Type>
207 class storage_for_object :
208     aligned_storage< sizeof(Type), align_of<Type>::value >
209 {
210 public:
211     /// Return a typed reference to the buffer.
object()212     const Type& object() const { return *reinterpret_cast<Type*>(this); }
object()213           Type& object()       { return *reinterpret_cast<Type*>(this); }
214 };
215 
216 
217 /** Get the functor class corresponding to a binary function type.
218  *
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.
222  *
223  *  @tparam F   A binary functor class, a binary function type, or a pointer to
224  *              binary function type.
225  *
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.)
232  *
233  *  @ingroup common
234  */
235 template <typename F>
236 struct binary_functor {
237      /// The binary functor class equivalent to @a F.
238      typedef F type;
239 };
240 
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;
247 };
248 
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;
255 };
256 
257 
258 /** Indirect binary function class with specified types.
259  *
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.
266  *
267  *  That is, suppose that we have the declarations:
268  *
269  *      F *p;
270  *      typed_indirect_binary_function<F, int, int, bool> ibf(p);
271  *
272  *  Then:
273  *
274  *  -   `ibf(x, y) == (*p)(x, y)`.
275  *  -   `ibf(x, y)` will not do a pointer dereference if `F` is an empty class.
276  *
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.
284  *
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.
290  *
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.
296  *
297  *  @see min_max::comparator_base
298  *  @see indirect_binary_function
299  *
300  *  @ingroup common
301  */
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
308          >
309 class typed_indirect_binary_function : std::binary_function<A1, A2, R>
310 {
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) {}
315 
316     /// Return the comparator pointer, or `NULL` if the comparator is stateless.
317     const F* pointer() const { return f; }
318 
319     /// Apply the pointed-to functor to the arguments.
320     R operator()(const A1& a1, const A2& a2) const { return (*f)(a1, a2); }
321 };
322 
323 
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>
331 {
332 public:
333     /// Return `NULL` for the comparator pointer of a stateless comparator.
334     const F* pointer() const { return 0; }
335 
336     /// Constructor discards the pointer to a stateless functor class.
337     typed_indirect_binary_function(const F* f) {}
338 
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); }
341 };
342 
343 
344 /** Indirect binary function class with inferred types.
345  *
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`.
350  *
351  *  @see typed_indirect_binary_function
352  *
353  *  @ingroup common
354  */
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
361                                   >
362 {
363     typedef     typed_indirect_binary_function< F
364                                   , typename Functor::first_argument_type
365                                   , typename Functor::second_argument_type
366                                   , typename Functor::result_type
367                                   >
368                 base;
369 public:
370     indirect_binary_function(const F* f) : base(f) {} ///< Constructor
371 };
372 
373 
374 /** Choose a type based on a boolean constant.
375  *
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.
379  *
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.
385  *
386  *  @ingroup common
387  */
388 template <bool Cond, typename IfTrue, typename IfFalse>
389 struct condition
390 {
391     typedef IfTrue type;    ///< The type selected by the condition.
392 };
393 
394 /// @copydoc condition
395 /// Specialization for @a Cond == `false`.
396 template <typename IfTrue, typename IfFalse>
397 struct condition<false, IfTrue, IfFalse>
398 {
399     typedef IfFalse type;   ///< The type selected by the condition.
400 };
401 
402 
403 /** @def __CILKRTS_STATIC_ASSERT
404  *
405  *  @brief Compile-time assertion.
406  *
407  *  Causes a compilation error if a compile-time constant expression is false.
408  *
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.
413  *
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");
417  *
418  *  @note   In a C++11 compiler, this is just the language predefined
419  *          `static_assert` macro.
420  *
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.
424  *
425  *  @param  Cond    The expression to test.
426  *  @param  Msg     A string explaining the failure.
427  *
428  *  @ingroup common
429  */
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]
436 
437 /// @cond internal
438     template <bool> struct static_assert_failure { };
439     template <> struct static_assert_failure<true> { enum { Success = 1 }; };
440 
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
447 
448 #endif
449 
450 /// @cond internal
451 
452 /** @name Aligned heap management.
453  */
454 //@{
455 
456 /** Implementation-specific aligned memory allocation function.
457  *
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.
463  *
464  *  @see                deallocate_aligned()
465  */
466 inline void* allocate_aligned(std::size_t size, std::size_t alignment)
467 {
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
478 }
479 
480 /** Implementation-specific aligned memory deallocation function.
481  *
482  *  @param  ptr A pointer which was returned by a call to alloc_aligned().
483  */
484 inline void deallocate_aligned(void* ptr)
485 {
486 #ifdef _WIN32
487     _aligned_free(ptr);
488 #else
489     std::free(ptr);
490 #endif
491 }
492 
493 /** Class to allocate and guard an aligned pointer.
494  *
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.
498  *
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.
501  */
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;
518     }
519 };
520 
521 //@}
522 
523 /// @endcond
524 
525 } // namespace internal
526 
527 //@{
528 
529 /** Allocate an aligned data structure on the heap.
530  *
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`.
534  *
535  *  @ingroup common
536  */
537 template <typename T>
538 T* aligned_new()
539 {
540     internal::new_aligned_pointer<T> ptr;
541     new (ptr) T();
542     return ptr.ok();
543 }
544 
545 template <typename T, typename T1>
546 T* aligned_new(const T1& x1)
547 {
548     internal::new_aligned_pointer<T> ptr;
549     new (ptr) T(x1);
550     return ptr.ok();
551 }
552 
553 template <typename T, typename T1, typename T2>
554 T* aligned_new(const T1& x1, const T2& x2)
555 {
556     internal::new_aligned_pointer<T> ptr;
557     new (ptr) T(x1, x2);
558     return ptr.ok();
559 }
560 
561 template <typename T, typename T1, typename T2, typename T3>
562 T* aligned_new(const T1& x1, const T2& x2, const T3& x3)
563 {
564     internal::new_aligned_pointer<T> ptr;
565     new (ptr) T(x1, x2, x3);
566     return ptr.ok();
567 }
568 
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)
571 {
572     internal::new_aligned_pointer<T> ptr;
573     new (ptr) T(x1, x2, x3, x4);
574     return ptr.ok();
575 }
576 
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)
579 {
580     internal::new_aligned_pointer<T> ptr;
581     new (ptr) T(x1, x2, x3, x4, x5);
582     return ptr.ok();
583 }
584 
585 //@}
586 
587 
588 /** Deallocate an aligned data structure on the heap.
589  *
590  *  `cilk::aligned_delete(ptr)` is equivalent to `delete ptr`, except that it
591  *  operates on a pointer that was allocated by aligned_new().
592  *
593  *  @ingroup common
594  */
595 template <typename T>
596 void aligned_delete(const T* ptr)
597 {
598     ptr->~T();
599     internal::deallocate_aligned((void*)ptr);
600 }
601 
602 } // namespace cilk
603 
604 #endif // __cplusplus
605 
606 #endif // METAPROGRAMMING_H_INCLUDED
607