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