2015-08-01 Michael Collison <michael.collison@linaro.org
[official-gcc.git] / libcilkrts / include / cilk / reducer.h
bloba22651e1e6f9db577882a979247e9a9d267b54dd
1 /* reducer.h -*- C++ -*-
3 * @copyright
4 * Copyright (C) 2009-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 reducer.h
39 * @brief Defines foundation classes for creating Cilk reducers.
41 * @ingroup Reducers
43 * @see @ref pagereducers
45 * @defgroup Reducers Reducers
48 #ifndef REDUCER_H_INCLUDED
49 #define REDUCER_H_INCLUDED
51 #include "cilk/hyperobject_base.h"
52 #include "cilk/metaprogramming.h"
54 #ifdef __cplusplus
56 //===================== C++ interfaces ===================================
58 #include <new>
60 namespace cilk {
62 /** Base class for defining monoids.
64 * The monoid_base class template is useful for creating classes that model
65 * the monoid concept. It provides the core type and memory management
66 * functionality. A subclass of monoid_base need only declare and implement
67 * the `identity` and `reduce` functions.
69 * The monoid_base class also manages the integration between the monoid, the
70 * reducer class that is based on it, and an optional view class which wraps
71 * value objects and restricts access to their operations.
73 * @tparam Value The value type for the monoid.
74 * @tparam View An optional view class that serves as a proxy for the value
75 * type.
77 * @see monoid_with_view
79 template <typename Value, typename View = Value>
80 class monoid_base
82 protected:
84 /** Class for provisionally constructed objects.
86 * The monoid_base::construct() functions manually construct both a monoid
87 * and a view. If one of these is constructed successfully, and the
88 * construction of the other (or some other initialization) fails, then
89 * the first one must be destroyed to avoid a memory leak. Because the
90 * construction is explicit, the destruction must be explicit, too.
92 * A provisional_guard object wraps a pointer to a newly constructed
93 * object. A call to its confirm() function confirms that the object is
94 * really going to be used. If the guard is destroyed without being
95 * confirmed, then the pointed-to object is destroyed (but not
96 * deallocated).
98 * Expected usage:
100 * provisional_guard<T1> x1_provisional( new (x1) T1() );
101 * … more initialization …
102 * x1_provisional.confirm();
104 * or
106 * provisional_guard<T1> x1_provisional( new (x1) T1() );
107 * x1_provisional.confirm_if( new (x2) T2() );
109 * If an exception is thrown in the “more initialization” code in the
110 * first example, or in the `T2` constructor in the second example, then
111 * `x1_provisional` will not be confirmed, so when its destructor is
112 * called during exception unwinding, the `T1` object that was constructed
113 * in `x1` will be destroyed.
115 * @see provisional()
117 * @tparam Type The type of the provisionally constructed object.
119 template <typename Type>
120 class provisional_guard {
121 Type* m_ptr;
123 public:
125 /** Constructor. Creates a guard for a provisionally constructed object.
127 * @param ptr A pointer to the provisionally constructed object.
129 provisional_guard(Type* ptr) : m_ptr(ptr) {}
131 /** Destructor. Destroy the object pointed to by the contained pointer
132 * if it has not been confirmed.
134 ~provisional_guard() { if (m_ptr) m_ptr->~Type(); }
136 /** Confirm the provisional construction. Do *not* delete the contained
137 * pointer when the guard is destroyed.
139 void confirm() { m_ptr = 0; }
141 /** Confirm provisional construction if argument is non-null. Note that
142 * if an exception is thrown during evaluation of the argument
143 * expression, then this function will not be called, and the
144 * provisional object will not be confirmed. This allows the usage:
146 * x1_provisional.confirm_if( new (x2) T2() );
148 * @param cond An arbitrary pointer. The provisional object will be
149 * confirmed if @a cond is not null.
151 * @returns The value of the @a cond argument.
153 template <typename Cond>
154 Cond* confirm_if(Cond* cond) { if (cond) m_ptr = 0; return cond; }
158 /** Create a provisional_guard object. This function allows simpler code
159 * when the only use of a provisional_guard is in a
160 * provisional_guard::confirm_if() call immediately following its
161 * creation. Instead of
163 * provisional_guard<T>guard( new (ptr_to_T) T() );
164 * guard.confirm_if( new (ptr_to_U) U() );
166 * you can just write
168 * provisional( new (ptr_to_T) T() ).confirm_if( new (ptr_to_U) U() );
170 * @tparam Type The type of the provisionally constructed object.
172 * @param ptr A pointer to a provisionally constructed object.
174 * @returns A @ref provisional_guard object that guards the
175 * provisionally constructed object pointed to by @a ptr.
177 template <typename Type>
178 static provisional_guard<Type> provisional(Type* ptr)
179 { return provisional_guard<Type>(ptr); }
181 public:
183 /** Value type of the monoid.
185 typedef Value value_type;
187 /** View type of the monoid. Defaults to be the same as the value type.
188 * @see monoid_with_view
190 typedef View view_type;
192 enum {
193 /** Should reducers created with this monoid be aligned?
195 * @details
196 * “Aligned” means that the view is allocated at a cache-line aligned
197 * offset in the reducer, and the reducer must be cache-line aligned.
198 * “Unaligned” means that the reducer as a whole is just naturally
199 * aligned, but it contains a large enough block of uninitialized
200 * storage for a cache-line aligned view to be allocated in it at
201 * reducer construction time.
203 * Since the standard heap allocator (new reducer) does not allocate
204 * cache-line aligned storage, only unaligned reducers can be safely
205 * allocated on the heap.
207 * Default is false (unaligned) unless overridden in a subclass.
209 * @since 1.02
210 * (In Cilk library versions 1.0 and 1.01, the default was true.
211 * In Cilk library versions prior to 1.0, reducers were always aligned,
212 * and this data member did not exist.)
214 align_reducer = false
217 /** Destroy a view. Destroys (without deallocating) the @a View object
218 * pointed to by @a p.
220 * @param p The address of the @a View object to be destroyed.
222 void destroy(view_type* p) const { p->~view_type(); }
224 /** Allocate raw memory. Allocate @a s bytes of memory with no
225 * initialization.
227 * @param s The number of bytes of memory to allocate.
228 * @return An untyped pointer to the allocated memory.
230 void* allocate(size_t s) const { return operator new(s); }
232 /** Deallocate raw memory. Deallocates the memory pointed to by @a p
233 * without doing any destruction.
235 * @param p Pointer to the memory to be deallocated.
237 * @pre @a p points to a block of memory that was allocated by a
238 * call to allocate().
240 void deallocate(void* p) const { operator delete(p); }
242 /** Create the identity value. Constructs (without allocating) a @a View
243 * object representing the default value of the @a Value type.
245 * @param p A pointer to a block of raw memory large enough to hold a
246 * @a View object.
248 * @post The memory pointed to by @a p contains a @a View object that
249 * represents the default value of the @a View type.
251 * @deprecated This function constructs the @a View object with its default
252 * constructor, which will often, but not always, yield the
253 * appropriate identity value. Monoid classes should declare
254 * their identity function explicitly, rather than relying on
255 * this default definition.
257 void identity(View* p) const { new ((void*) p) View(); }
260 /** @name Construct the monoid and the view with arbitrary arguments.
262 * A @ref reducer object contains monoid and view data members, which are
263 * declared as raw storage (byte arrays), so that they are not implicitly
264 * constructed when the reducer is constructed. Instead, a reducer
265 * constructor calls one of the monoid class’s static construct()
266 * functions with the addresses of the monoid and the view, and the
267 * construct() function uses placement `new` to construct them.
269 * This allows the monoid to determine the order in which the monoid and
270 * view are constructed, and to make one of them dependent on the other.
272 * Any arguments to the reducer constructor are just passed on as
273 * additional arguments to the construct() function (after the monoid
274 * and view addresses).
276 * Any monoid whose needs are satisfied by the suite of construct()
277 * functions below, such as @ref monoid_with_view, can just inherit them
278 * from monoid_base. Other monoids will need to provide their own versions
279 * to override the monoid_base functions.
281 //@{
283 /** Default-construct the monoid, and pass zero to five const reference
284 * arguments to the view constructor.
286 //@{
288 template <typename Monoid>
289 static void construct(Monoid* monoid, View* view)
290 { provisional( new ((void*)monoid) Monoid() ).confirm_if(
291 (monoid->identity(view), view) ); }
293 template <typename Monoid, typename T1>
294 static void construct(Monoid* monoid, View* view, const T1& x1)
295 { provisional( new ((void*)monoid) Monoid() ).confirm_if(
296 new ((void*)view) View(x1) ); }
298 template <typename Monoid, typename T1, typename T2>
299 static void construct(Monoid* monoid, View* view,
300 const T1& x1, const T2& x2)
301 { provisional( new ((void*)monoid) Monoid() ).confirm_if(
302 new ((void*)view) View(x1, x2) ); }
304 template <typename Monoid, typename T1, typename T2, typename T3>
305 static void construct(Monoid* monoid, View* view,
306 const T1& x1, const T2& x2, const T3& x3)
307 { provisional( new ((void*)monoid) Monoid() ).confirm_if(
308 new ((void*)view) View(x1, x2, x3) ); }
310 template <typename Monoid, typename T1, typename T2, typename T3,
311 typename T4>
312 static void construct(Monoid* monoid, View* view,
313 const T1& x1, const T2& x2, const T3& x3,
314 const T4& x4)
315 { provisional( new ((void*)monoid) Monoid() ).confirm_if(
316 new ((void*)view) View(x1, x2, x3, x4) ); }
318 template <typename Monoid, typename T1, typename T2, typename T3,
319 typename T4, typename T5>
320 static void construct(Monoid* monoid, View* view,
321 const T1& x1, const T2& x2, const T3& x3,
322 const T4& x4, const T5& x5)
323 { provisional( new ((void*)monoid) Monoid() ).confirm_if(
324 new ((void*)view) View(x1, x2, x3, x4, x5) ); }
326 //@}
328 /** Default-construct the monoid, and pass one non-const reference argument
329 * to the view constructor.
331 //@{
332 template <typename Monoid, typename T1>
333 static void construct(Monoid* monoid, View* view, T1& x1)
334 { provisional( new ((void*)monoid) Monoid() ).confirm_if(
335 new ((void*)view) View(x1) ); }
336 //@}
338 /** Copy-construct the monoid, and pass zero to four const reference
339 * arguments to the view constructor.
341 //@{
343 template <typename Monoid>
344 static void construct(Monoid* monoid, View* view, const Monoid& m)
345 { provisional( new ((void*)monoid) Monoid(m) ).confirm_if(
346 new ((void*)view) View() ); }
348 template <typename Monoid, typename T1>
349 static void construct(Monoid* monoid, View* view, const Monoid& m,
350 const T1& x1)
351 { provisional( new ((void*)monoid) Monoid(m) ).confirm_if(
352 new ((void*)view) View(x1) ); }
354 template <typename Monoid, typename T1, typename T2>
355 static void construct(Monoid* monoid, View* view, const Monoid& m,
356 const T1& x1, const T2& x2)
357 { provisional( new ((void*)monoid) Monoid(m) ).confirm_if(
358 new ((void*)view) View(x1, x2) ); }
360 template <typename Monoid, typename T1, typename T2, typename T3>
361 static void construct(Monoid* monoid, View* view, const Monoid& m,
362 const T1& x1, const T2& x2, const T3& x3)
364 provisional( new ((void*)monoid) Monoid(m) ).confirm_if(
365 new ((void*)view) View(x1, x2, x3) );
368 template <typename Monoid, typename T1, typename T2, typename T3,
369 typename T4>
370 static void construct(Monoid* monoid, View* view, const Monoid& m,
371 const T1& x1, const T2& x2, const T3& x3,
372 const T4& x4)
374 provisional( new ((void*)monoid) Monoid(m) ).confirm_if(
375 new ((void*)view) View(x1, x2, x3, x4) );
378 //@}
380 //@}
384 /** Monoid class that gets its value type and identity and reduce operations
385 * from its view.
387 * A simple implementation of the monoid-view-reducer architecture would
388 * distribute knowledge about the type and operations for the reduction
389 * between the monoid and the view — the identity and reduction operations are
390 * specified in the monoid, the reduction operations are implemented in the
391 * view, and the value type is specified in both the monoid and the view.
392 * This is inelegant.
394 * monoid_with_view is a subclass of @ref monoid_base that gets its value type
395 * and its identity and reduction operations from its view class. No
396 * customization of the monoid_with_view class itself is needed beyond
397 * instantiating it with an appropriate view class. (Customized subclasses of
398 * monoid_with_view may be needed for other reasons, such as to keep some
399 * state for the reducer.) All of the Cilk predefined reducers use
400 * monoid_with_view or one of its subclasses.
402 * The view class `View` of a monoid_with_view must provide the following public definitions:
404 * Definition | Meaning
405 * ---------------------------------|--------
406 * `value_type` | a typedef of the value type for the reduction
407 * `View()` | a default constructor which constructs the identity value for the reduction
408 * `void reduce(const View* other)` | a member function which applies the reduction operation to the values of `this` view and the `other` view, leaving the result as the value of `this` view, and leaving the value of the `other` view undefined (but valid)
410 * @tparam View The view class for the monoid.
411 * @tparam Align If true, reducers instantiated on this monoid will be
412 * cache-aligned. By default, library reducers (unlike legacy
413 * library reducer _wrappers_) are aligned only as required by
414 * contents.
416 template <class View, bool Align = false>
417 class monoid_with_view : public monoid_base<typename View::value_type, View>
419 public:
420 /** Should reducers created with this monoid be aligned?
422 enum { align_reducer = Align };
424 /** Create the identity value.
426 * Implements the monoid `identity` operation by using the @a View class’s
427 * default constructor.
429 * @param p A pointer to a block of raw memory large enough to hold a
430 * @p View object.
432 void identity(View* p) const { new ((void*)p) View(); }
434 /** Reduce the values of two views.
436 * Implements the monoid `reduce` operation by calling the left view’s
437 * `%reduce()` function with the right view as an operand.
439 * @param left The left operand of the reduce operation.
440 * @param right The right operand of the reduce operation.
441 * @post The left view contains the result of the reduce
442 * operation, and the right view is undefined.
444 void reduce(View* left, View* right) const { left->reduce(right); }
448 /** Base class for simple views with (usually) scalar values.
450 * The scalar_view class is intended as a base class which provides about half
451 * of the required definitions for simple views. It defines the `value_type`
452 * required by a @ref monoid_with_view (but not the identity constructor and
453 * reduce operation, which are inherently specific to a particular kind of
454 * reduction). It also defines the value access functions which will be called
455 * by the corresponding @ref reducer functions. (It uses copy semantics for
456 * the view_move_in() and view_move_out() functions, which is appropriate
457 * for simple scalar types, but not necessarily for more complex types like
458 * STL containers.
460 * @tparam Type The type of value wrapped by the view.
462 template <typename Type>
463 class scalar_view
465 protected:
466 Type m_value; ///< The wrapped accumulator variable.
468 public:
469 /** Value type definition required by @ref monoid_with_view.
471 typedef Type value_type;
473 /** Default constructor.
475 scalar_view() : m_value() {}
477 /** Value constructor.
479 scalar_view(const Type& v) : m_value(v) {}
481 /** @name Value functions required by the reducer class.
483 * Note that the move in/out functions use simple assignment semantics.
485 //@{
487 /** Set the value of the view.
489 void view_move_in(Type& v) { m_value = v; }
491 /** Get the value of the view.
493 void view_move_out(Type& v) { v = m_value; }
495 /** Set the value of the view.
497 void view_set_value(const Type& v) { m_value = v; }
499 /** Get the value of the view.
501 Type const& view_get_value() const { return m_value; }
503 /** Get a reference to the value contained in the view. For legacy
504 * reducer support only.
506 Type & view_get_reference() { return m_value; }
508 /** Get a reference to the value contained in the view. For legacy
509 * reducer support only.
511 Type const& view_get_reference() const { return m_value; }
512 //@}
516 /** Wrapper class for move-in construction.
518 * Some types allow their values to be _moved_ as an alternative to copying.
519 * Moving a value may be much faster than copying it, but may leave the value
520 * of the move’s source undefined. Consider the `swap` operation provided by
521 * many STL container classes:
523 * list<T> x, y;
524 * x = y; // Copy
525 * x.swap(y); // Move
527 * The assignment _copies_ the value of `y` into `x` in time linear in the
528 * size of `y`, leaving `y` unchanged. The `swap` _moves_ the value of `y`
529 * into `x` in constant time, but it also moves the value of `x` into `y`,
530 * potentially leaving `y` undefined.
532 * A move_in_wrapper simply wraps a pointer to an object. It is created by a
533 * call to cilk::move_in(). Passing a move_in_wrapper to a view constructor
534 * (actually, passing it to a reducer constructor, which passes it to the
535 * monoid `construct()` function, which passes it to the view constructor)
536 * allows, but does not require, the value pointed to by the wrapper to be
537 * moved into the view instead of copied.
539 * A view class exercises this option by defining a _move-in constructor_,
540 * i.e., a constructor with a move_in_wrapper parameter. The constructor calls
541 * the wrapper’s `value()` function to get a reference to its pointed-to
542 * value, and can then use that reference in a move operation.
544 * A move_in_wrapper also has an implicit conversion to its pointed-to value,
545 * so if a view class does not define a move-in constructor, its ordinary
546 * value constructor will be called with the wrapped value. For example, an
547 * @ref ReducersAdd "op_add" view does not have a move-in constructor, so
549 * int x;
550 * reducer< op_add<int> > xr(move_in(x));
552 * will simply call the `op_add_view(const int &)` constructor. But an
553 * @ref ReducersList "op_list_append" view does have a move-in constructor,
554 * so
556 * list<int> x;
557 * reducer< op_list_append<int> > xr(move_in(x));
559 * will call the `op_list_append_view(move_in_wrapper<int>)` constructor,
560 * which can `swap` the value of `x` into the view.
562 * @note Remember that passing the value of a variable to a reducer
563 * constructor using a move_in_wrapper leaves the variable undefined.
564 * You cannot assume that the constructor either will or will not copy
565 * or move the value.
567 * @tparam Type The type of the wrapped value.
569 * @see cilk::move_in()
571 template <typename Type>
572 class move_in_wrapper
574 Type *m_pointer;
575 public:
577 /** Constructor that captures the address of its argument. This is almost
578 * always called from the @ref move_in function.
580 explicit move_in_wrapper(Type& ref) : m_pointer(&ref) { }
582 /** Implicit conversion to the wrapped value. This allows a move_in_wrapper
583 * to be used where a value of the wrapped type is expected, in which case
584 * the wrapper is completely transparent.
586 operator Type&() const { return *m_pointer; }
588 /** Get a reference to the pointed-to value. This has the same effect as
589 * the implicit conversion, but makes the intent clearer in a move-in
590 * constructor.
592 Type& value() const { return *m_pointer; }
595 /** Function to create a move_in_wrapper for a value.
597 * @tparam Type The type of the argument, which will be the `type` of the
598 * created wrapper.
600 * @see move_in_wrapper
602 template <typename Type>
603 inline
604 move_in_wrapper<Type> move_in(Type& ref)
605 { return move_in_wrapper<Type>(ref); }
608 /** @copydoc move_in(Type&)
610 * @note Applying a function that is explicitly specified as modifying its
611 * argument to a const argument is obviously an irrational thing to
612 * do. This move_in() variant is just provided to allow calling a
613 * move-in constructor with a function return value, which the
614 * language treats as a const. Using it for any other purpose will
615 * probably end in tears.
617 template <typename Type>
618 inline
619 move_in_wrapper<Type> move_in(const Type& ref)
620 { return move_in_wrapper<Type>(ref); }
623 /** Wrapper class to allow implicit downcasts to reducer subclasses.
625 * The Cilk library contains a collection of reducer wrapper classes which
626 * were created before the `cilk::reducer<Monoid>` style was developed. For
627 * example, `cilk::reducer_opadd<Type>` provided essentially the same
628 * functionality that is now provided by
629 * `cilk::reducer< cilk::op_add<Type> >`. These legacy reducer classes are
630 * deprecated, but still supported, and they have been reimplemented as
631 * subclasses of the corresponding `cilk::reducer` classes. For example:
633 * template <class T>
634 * reducer_opadd<T> : public reducer< op_add<T> > { ... };
636 * This reimplementation allows transparent conversion between legacy and
637 * new reducers. That is, a `reducer<op_add>*` or `reducer<op_add>&` can be
638 * used anywhere that a `reducer_opadd*` or `reducer_opadd&` is expected,
639 * and vice versa.
641 * The conversion from the legacy reducer to the new reducer is just an
642 * up-cast, which is provided for free by C++. The conversion from the new
643 * reducer to the legacy reducer is a down-cast, though, which requires an
644 * explicit conversion member function in the `reducer` class. The challenge
645 * is to define a function in the reducer template class which will convert
646 * each cilk::reducer specialization to the corresponding legacy reducer,
647 * if there is one.
649 * The trick is in the legacy_reducer_downcast template class, which provides
650 * a mapping from `cilk::reducer` specializations to legacy reducer classes.
651 * `reducer<Monoid>` has a conversion function to convert itself to
652 * `legacy_reducer_downcast< reducer<Monoid> >::%type`. By default,
653 * `legacy_reducer_downcast<Reducer>::%type` is just a trivial subclass of
654 * `Reducer`, which is uninteresting, but a reducer with a legacy counterpart
655 * will have a specialization of `legacy_reducer_downcast` whose `type` is
656 * the corresponding legacy reducer. For example:
658 * template <typename Type>
659 * struct legacy_reducer_downcast< reducer< op_add<Type> > >
661 * typedef reducer_opadd<Type> type;
662 * };
665 * @tparam Reducer The new-style reducer class whose corresponding legacy reducer class
666 * is `type`, if there is such a legacy reducer class.
668 template <typename Reducer>
669 struct legacy_reducer_downcast
671 /** The related legacy reducer class.
673 * By default, this is just a trivial subclass of Reducer, but it can be
674 * overridden in the specialization of legacy_reducer_downcast for
675 * a reducer that has a corresponding legacy reducers.
677 struct type : Reducer { };
681 namespace internal {
682 /// @cond internal
684 template <typename Value, typename View>
685 struct reducer_set_get
687 static View theView; // Declared but not defined
689 // sizeof(notchar) is guaranteed larger than 1
690 struct notchar { char x[2]; };
692 // check_for_ref returns char if 'get_value' returns by value and notchar
693 // if 'get_value' returns by reference.
694 static char check_for_ref(Value, ...);
695 static notchar check_for_ref(Value&, int);
697 enum { GET_VALUE_BY_VALUE =
698 (1 == sizeof(check_for_ref(theView.view_get_value(), 0))) } ;
700 typedef typename condition<GET_VALUE_BY_VALUE,
701 Value, const Value&>::type get_value_type;
703 static void move_in(View& view, Value& v) { view.view_move_in(v); }
704 static void move_out(View& view, Value& v) { view.view_move_out(v); }
706 static void set_value(View& view, const Value& v)
707 { view.view_set_value(v); }
709 static get_value_type get_value(const View& view)
710 { return view.view_get_value(); }
713 template <typename Value>
714 struct reducer_set_get<Value, Value>
716 typedef const Value& get_value_type;
718 static void move_in(Value& view, Value& v) { view = v; }
719 static void move_out(Value& view, Value& v) { v = view; }
721 static void set_value(Value& view, const Value& v) { view = v; }
723 static get_value_type get_value(const Value& view) { return view; }
726 /// @endcond
729 /** Base class defining the data layout that is common to all reducers.
731 template <typename Monoid>
732 class reducer_base {
733 typedef typename Monoid::view_type view_type;
735 // This makes the reducer a hyper-object. (Partially initialized in
736 // the derived reducer_content class.)
738 __cilkrts_hyperobject_base m_base;
740 // The monoid is allocated here as raw bytes, and is constructed explicitly
741 // by a call to the monoid_type::construct() function in the constructor of
742 // the `reducer` subclass.
744 storage_for_object<Monoid> m_monoid;
746 // Used for sanity checking at destruction.
748 void* m_initialThis;
750 // The leftmost view comes next. It is defined in the derived
751 // reducer_content class.
753 /** @name C-callable wrappers for the C++-coded monoid dispatch functions.
755 //@{
757 static void reduce_wrapper(void* r, void* lhs, void* rhs);
758 static void identity_wrapper(void* r, void* view);
759 static void destroy_wrapper(void* r, void* view);
760 static void* allocate_wrapper(void* r, __STDNS size_t bytes);
761 static void deallocate_wrapper(void* r, void* view);
763 //@}
765 protected:
767 /** Constructor.
769 * @param leftmost The address of the leftmost view in the reducer.
771 reducer_base(char* leftmost)
773 static const cilk_c_monoid c_monoid_initializer = {
774 (cilk_c_reducer_reduce_fn_t) &reduce_wrapper,
775 (cilk_c_reducer_identity_fn_t) &identity_wrapper,
776 (cilk_c_reducer_destroy_fn_t) &destroy_wrapper,
777 (cilk_c_reducer_allocate_fn_t) &allocate_wrapper,
778 (cilk_c_reducer_deallocate_fn_t) &deallocate_wrapper
781 m_base.__c_monoid = c_monoid_initializer;
782 m_base.__flags = 0;
783 m_base.__view_offset = (char*)leftmost - (char*)this;
784 m_base.__view_size = sizeof(view_type);
785 m_initialThis = this;
787 __cilkrts_hyper_create(&m_base);
790 /** Destructor.
792 __CILKRTS_STRAND_STALE(~reducer_base())
794 // Make sure we haven't been memcopy'd or corrupted
795 __CILKRTS_ASSERT(
796 this == m_initialThis ||
797 // Allow for a layout bug that may put the initialThis field one
798 // word later in 1.0 reducers than in 0.9 and 1.1 reducers.
799 this == *(&m_initialThis + 1)
801 __cilkrts_hyper_destroy(&m_base);
804 /** Monoid data member.
806 * @return A pointer to the reducer’s monoid data member.
808 Monoid* monoid_ptr() { return &m_monoid.object(); }
810 /** Leftmost view data member.
812 * @return A pointer to the reducer’s leftmost view data member.
814 * @note This function returns the address of the *leftmost* view,
815 * which is unique for the lifetime of the reducer. It is
816 * intended to be used in constructors and destructors.
817 * Use the reducer::view() function to access the per-strand
818 * view instance.
820 view_type* leftmost_ptr()
822 char* view_addr = (char*)this + m_base.__view_offset;
823 return reinterpret_cast<view_type*>(view_addr);
826 public:
828 /** @name Access the current view.
830 * These functions return a reference to the instance of the reducer’s
831 * view that was created for the current strand of a parallel computation
832 * (and create it if it doesn’t already exist). Note the difference from
833 * the (private) leftmost_ptr() function, which returns a pointer to the
834 * _leftmost_ view, which is the same in all strands.
836 //@{
838 /** Per-strand view instance.
840 * @return A reference to the per-strand view instance.
842 view_type& view()
844 return *static_cast<view_type *>(__cilkrts_hyper_lookup(&m_base));
847 /** @copydoc view()
849 const view_type& view() const
851 return const_cast<reducer_base*>(this)->view();
854 //@}
856 /** Initial view pointer field.
858 * @internal
860 * @return a reference to the m_initialThis field.
862 * @note This function is provided for “white-box” testing of the
863 * reducer layout code. There is never any reason for user code
864 * to call it.
866 const void* const & initial_this() const { return m_initialThis; }
869 template <typename Monoid>
870 void reducer_base<Monoid>::reduce_wrapper(void* r, void* lhs, void* rhs)
872 Monoid* monoid = static_cast<reducer_base*>(r)->monoid_ptr();
873 monoid->reduce(static_cast<view_type*>(lhs),
874 static_cast<view_type*>(rhs));
877 template <typename Monoid>
878 void reducer_base<Monoid>::identity_wrapper(void* r, void* view)
880 Monoid* monoid = static_cast<reducer_base*>(r)->monoid_ptr();
881 monoid->identity(static_cast<view_type*>(view));
884 template <typename Monoid>
885 void reducer_base<Monoid>::destroy_wrapper(void* r, void* view)
887 Monoid* monoid = static_cast<reducer_base*>(r)->monoid_ptr();
888 monoid->destroy(static_cast<view_type*>(view));
891 template <typename Monoid>
892 void* reducer_base<Monoid>::allocate_wrapper(void* r, __STDNS size_t bytes)
894 Monoid* monoid = static_cast<reducer_base*>(r)->monoid_ptr();
895 return monoid->allocate(bytes);
898 template <typename Monoid>
899 void reducer_base<Monoid>::deallocate_wrapper(void* r, void* view)
901 Monoid* monoid = static_cast<reducer_base*>(r)->monoid_ptr();
902 monoid->deallocate(static_cast<view_type*>(view));
906 /** Base class defining the data members of a reducer.
908 * @tparam Aligned The `m_view` data member, and therefore the entire
909 * structure, are cache-line aligned if this parameter
910 * is `true'.
912 template <typename Monoid, bool Aligned = Monoid::align_reducer>
913 class reducer_content;
915 /** Base class defining the data members of an aligned reducer.
917 template <typename Monoid>
918 class reducer_content<Monoid, true> : public reducer_base<Monoid>
920 typedef typename Monoid::view_type view_type;
922 // The leftmost view is defined as raw bytes. It will be constructed
923 // by the monoid `construct` function. It is cache-aligned, which
924 // will push it into a new cache line. Furthermore, its alignment causes
925 // the reducer as a whole to be cache-aligned, which makes the reducer
926 // size a multiple of a cache line. Since there is nothing in the reducer
927 // after the view, all this means that the leftmost view gets one or more
928 // cache lines all to itself, which prevents false sharing.
930 __CILKRTS_CACHE_ALIGN
931 char m_leftmost[sizeof(view_type)];
933 /** Test if the reducer is cache-line-aligned.
935 * Used in assertions.
937 bool reducer_is_cache_aligned() const
938 { return 0 == ((std::size_t) this & (__CILKRTS_CACHE_LINE__ - 1)); }
940 protected:
942 /** Constructor.
944 reducer_content() : reducer_base<Monoid>((char*)&m_leftmost)
946 #ifndef CILK_IGNORE_REDUCER_ALIGNMENT
947 assert(reducer_is_cache_aligned() &&
948 "Reducer should be cache aligned. Please see comments following this assertion for explanation and fixes.");
949 #endif
950 /* "REDUCER SHOULD BE CACHE ALIGNED" ASSERTION.
952 * This Reducer class instantiation specifies cache-line alignment of the
953 * leftmost view field (and, implicitly, of the reducer itself). You got
954 * this assertion because a reducer with this class was allocated at a
955 * non-cache-aligned address, probably because it was allocated on the
956 * heap with `new`. This can be a problem for two reasons:
958 * 1. If the leftmost view is not on a cache line by itself, there might
959 * be a slowdown resulting from accesses to the same cache line from
960 * different threads.
962 * 2. The compiler thinks that reducer is cache-line aligned, but it
963 * really isn't. If the reducer is contained in a structure, then the
964 * compiler will believe that the containing structure, and other
965 * fields contained in it, are also more aligned than they really
966 * are. In particular, if the structure contains a numeric array that
967 * is used in a vectorizable loop, then the compiler might generate
968 * invalid vector instructions, resulting in a runtime error.
970 * The compiler will always allocate reducer variables, and structure
971 * variables containing reducers, with their required alignment.
972 * Reducers, and structures containing a reducer, which are allocated
973 * on the heap with `new` will _not_ be properly aligned.
975 * There are three ways that you can fix this assertion failure.
977 * A. Rewrite your code to use the new-style `reducer< op_XXX<Type> >`
978 * instead of the legacy `reducer_XXX<type>`. The new-style reducers
979 * are not declared to be cache-aligned, and will work properly if
980 * they are not cache-aligned.
982 * B. If you must allocate an old-style reducer or a structure containing
983 * a reducer on the heap, figure out how to align it correctly. The
984 * suggested fix is to use `cilk::aligned_new()` and
985 * `cilk::aligned_delete()` instead of `new` and `delete`, as follows:
987 * Type* ptr = cilk::aligned_new<Type>(constructor-arguments);
988 * cilk::aligned_delete(ptr);
990 * C. Define the macro CILK_IGNORE_REDUCER_ALIGNMENT, which will suppress
991 * the assertion check. Do this only if you are comfortable that
992 * problem (2) above will not occur.
997 /** Base class defining the data members of an unaligned reducer.
999 template <typename Monoid>
1000 class reducer_content<Monoid, false> : public reducer_base<Monoid>
1002 typedef typename Monoid::view_type view_type; ///< The view type.
1004 // Reserve space for the leftmost view. The view will be allocated at an
1005 // aligned offset in this space at runtime, to guarantee that the view
1006 // will get one or more cache lines all to itself, to prevent false
1007 // sharing.
1009 // The number of bytes to reserve is determined as follows:
1010 // * Start with the view size.
1011 // * Round up to a multiple of the cache line size, to get the total size
1012 // of the cache lines that will be dedicated to the view.
1013 // * Add (cache line size - 1) filler bytes to guarantee that the reserved
1014 // area will contain a cache-aligned block of the required cache lines,
1015 // no matter where the reserved area starts.
1017 char m_leftmost[
1018 // View size rounded up to multiple cache lines
1019 ( (sizeof(view_type) + __CILKRTS_CACHE_LINE__ - 1)
1020 & ~ (__CILKRTS_CACHE_LINE__ - 1)
1022 // plus filler to allow alignment.
1023 + __CILKRTS_CACHE_LINE__ - 1
1026 protected:
1028 /** Constructor. Find the first cache-aligned position in the reserved
1029 * area, and pass it to the base constructor as the leftmost view
1030 * address.
1032 reducer_content() :
1033 reducer_base<Monoid>(
1034 (char*)( ((std::size_t)&m_leftmost + __CILKRTS_CACHE_LINE__ - 1)
1035 & ~ (__CILKRTS_CACHE_LINE__ - 1) ) )
1040 } // namespace internal
1043 // The __cilkrts_hyperobject_ functions are defined differently depending on
1044 // whether a file is compiled with or without the CILK_STUB option. Therefore,
1045 // reducers compiled in the two modes should be link-time incompatible, so that
1046 // object files compiled with stubbed reducers won't be linked into an
1047 // unstubbed program, or vice versa. We achieve this by putting the reducer
1048 // class definition into the cilk::stub namespace in a stubbed compilation.
1050 #ifdef CILK_STUB
1051 namespace stub {
1052 #endif
1054 /** Reducer class.
1056 * A reducer is instantiated on a Monoid. The Monoid provides the value
1057 * type, associative reduce function, and identity for the reducer.
1059 * @tparam Monoid The monoid class that the reducer is instantiated on. It must model
1060 * the @ref reducers_monoid_concept "monoid concept".
1062 * @see @ref pagereducers
1064 template <class Monoid>
1065 class reducer : public internal::reducer_content<Monoid>
1067 typedef internal::reducer_content<Monoid> base;
1068 using base::monoid_ptr;
1069 using base::leftmost_ptr;
1070 public:
1071 typedef Monoid monoid_type; ///< The monoid type.
1072 typedef typename Monoid::value_type value_type; ///< The value type.
1073 typedef typename Monoid::view_type view_type; ///< The view type.
1075 private:
1076 typedef internal::reducer_set_get<value_type, view_type> set_get;
1078 reducer(const reducer&); ///< Disallow copying.
1079 reducer& operator=(const reducer&); ///< Disallow assignment.
1081 public:
1083 /** @name Constructors
1085 * All reducer constructors call the static `construct()` function of the monoid class to
1086 * construct the reducer's monoid and leftmost view.
1088 * The reducer constructor arguments are simply passed through to the construct() function.
1089 * Thus, the constructor parameters accepted by a particular reducer class are determined
1090 * by its monoid class.
1092 //@{
1094 /** 0 – 6 const reference parameters.
1096 //@{
1098 reducer()
1100 monoid_type::construct(monoid_ptr(), leftmost_ptr());
1103 template <typename T1>
1104 reducer(const T1& x1)
1106 monoid_type::construct(monoid_ptr(), leftmost_ptr(), x1);
1109 template <typename T1, typename T2>
1110 reducer(const T1& x1, const T2& x2)
1112 monoid_type::construct(monoid_ptr(), leftmost_ptr(), x1, x2);
1115 template <typename T1, typename T2, typename T3>
1116 reducer(const T1& x1, const T2& x2, const T3& x3)
1118 monoid_type::construct(monoid_ptr(), leftmost_ptr(), x1, x2, x3);
1121 template <typename T1, typename T2, typename T3, typename T4>
1122 reducer(const T1& x1, const T2& x2, const T3& x3, const T4& x4)
1124 monoid_type::construct(monoid_ptr(), leftmost_ptr(), x1, x2, x3, x4);
1127 template <typename T1, typename T2, typename T3, typename T4, typename T5>
1128 reducer(const T1& x1, const T2& x2, const T3& x3, const T4& x4, const T5& x5)
1130 monoid_type::construct(monoid_ptr(), leftmost_ptr(), x1, x2, x3, x4, x5);
1133 template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
1134 reducer(const T1& x1, const T2& x2, const T3& x3, const T4& x4, const T5& x5, const T6& x6)
1136 monoid_type::construct(monoid_ptr(), leftmost_ptr(), x1, x2, x3, x4, x5, x6);
1139 //@}
1141 /** 1 non-const reference parameter.
1143 //@{
1145 template <typename T1>
1146 reducer(T1& x1)
1148 monoid_type::construct(monoid_ptr(), leftmost_ptr(), x1);
1151 //@}
1153 /** Destructor.
1155 __CILKRTS_STRAND_STALE(~reducer())
1157 leftmost_ptr()->~view_type();
1158 monoid_ptr()->~monoid_type();
1161 //@{
1162 /** Get the monoid.
1164 * @return A reference to the monoid object belonging to this reducer.
1166 Monoid& monoid() { return *monoid_ptr(); }
1168 const Monoid& monoid() const
1169 { return const_cast<reducer*>(this)->monoid(); }
1170 //@}
1172 //@{
1173 /** Access the current view.
1175 * Return a reference to the instance of the reducer’s view that was
1176 * created for the current strand of a parallel computation (and create
1177 * it if it doesn’t already exist).
1179 view_type& view() { return base::view(); }
1180 const view_type& view() const { return base::view(); }
1181 //@}
1184 /** @name Dereference the reducer to get the view.
1186 * “Dereferencing” a reducer yields the view for the current strand. The
1187 * view, in turn, acts as a proxy for its contained value, exposing only
1188 * those operations which are consistent with the reducer’s monoid. Thus,
1189 * all modifications of the reducer’s accumulator variable are written as
1191 * *reducer OP ...
1193 * or
1195 * reducer->func(...)
1197 * (The permitted operations on a reducer’s accumulator are listed in the
1198 * documentation for that particular kind of reducer.)
1200 * @note `*r` is a synonym for `r.view()`. Recommended style is to use
1201 * `*r` (or `r->`) in the common case where code is simply
1202 * updating the accumulator variable wrapped in the view, and to
1203 * use `r.view()` in the unusual case where it is desirable to
1204 * call attention to the view itself.
1206 //@{
1208 //@{
1209 /** Dereference operator.
1211 * @return A reference to the per-strand view instance.
1213 view_type& operator*() { return view(); }
1214 view_type const& operator*() const { return view(); }
1215 //@}
1217 //@{
1218 /** Pointer operator.
1220 * @return A pointer to the per-strand view instance.
1222 view_type* operator->() { return &view(); }
1223 view_type const* operator->() const { return &view(); }
1224 //@}
1226 //@{
1227 /** Deprecated view access.
1229 * `r()` is a synonym for `*r` which was used with early versions of Cilk
1230 * reducers. `*r` is now the preferred usage.
1232 * @deprecated Use operator*() instead of operator()().
1234 * @return A reference to the per-strand view instance.
1236 view_type& operator()() { return view(); }
1237 view_type const& operator()() const { return view(); }
1238 //@}
1240 //@}
1242 /** @name Set and get the value.
1244 * These functions are used to set an initial value for the reducer before
1245 * starting the reduction, or to get the final value after the reduction
1246 * is complete.
1248 * @note These functions are completely different from the view
1249 * operations that are made available via operator*() and
1250 * operator->(), which are used to _modify_ the reducer’s value
1251 * _during_ the reduction.
1253 * @warning These functions _can_ be called at any time, and in
1254 * general, they will refer to the value contained in the view
1255 * for the current strand. However, using them other than to
1256 * set the reduction’s initial value or get its final value
1257 * will almost always result in undefined behavior.
1259 //@{
1261 /** Move a value into the reducer.
1263 * This function is used to set the initial value of the reducer’s
1264 * accumulator variable by either copying or _moving_ the value of @a obj
1265 * into it. Moving a value can often be performed in constant time, even
1266 * for large container objects, but has the side effect of leaving the
1267 * value of @a obj undefined. (See the description of the
1268 * @ref move_in_wrapper class for a discussion of moving values.)
1270 * @par Usage
1271 * A move_in() call to initialize a reducer is often paired with a
1272 * move_out() call to get its final value:
1274 * reducer<Type> xr;
1275 * xr.move_in(x);
1276 * … do the reduction …
1277 * xr.move_out(x);
1279 * @par Assumptions
1280 * - You cannot assume either that this will function will copy its
1281 * value or that it will move it.
1282 * - You must assume that the value of @a obj will be undefined
1283 * after the call to move_in().
1284 * - You can assume that move_in() will be at least as efficient as
1285 * set_value(), and you should therefore prefer move_in() unless
1286 * you need the value of @a obj to be unchanged after the call.
1287 * (But you should usually prefer the move-in constructor over a
1288 * move_in() call — see the note below.)
1290 * @note The behavior of a default constructor followed by move-in
1291 * initialization:
1293 * reducer<Type> xr;
1294 * xr.move_in(x);
1296 * @note is not necessarily the same as a move-in constructor:
1298 * reducer<Type> xr(move_in(x));
1300 * @note In particular, when @a Type is a container type with a
1301 * non-empty allocator, the move-in constructor will create the
1302 * accumulator variable with the same allocator as the input
1303 * argument @a x, while the default constructor will create the
1304 * accumulator variable with a default allocator. The mismatch of
1305 * allocators in the latter case means that the input argument
1306 * @a x may have to be copied in linear time instead of being
1307 * moved in constant time.
1309 * @note Best practice is to prefer the move-in constructor over the
1310 * move-in function unless the move-in function is required for
1311 * some specific reason.
1313 * @warning Calling this function other than to set the initial value
1314 * for a reduction will almost always result in undefined
1315 * behavior.
1317 * @param obj The object containing the value that will be moved into the
1318 * reducer.
1320 * @post The reducer contains the value that was initially in @a obj.
1321 * @post The value of @a obj is undefined.
1323 * @see set_value()
1325 void move_in(value_type& obj) { set_get::move_in(view(), obj);}
1327 /** Move the value out of the reducer.
1329 * This function is used to retrieve the final value of the reducer’s
1330 * accumulator variable by either copying or _moving_ the value of @a obj
1331 * into it. Moving a value can often be performed in constant time, even
1332 * for large container objects, but has the side effect of leaving the
1333 * value of the reducer’s accumulator variable undefined. (See the
1334 * description of the @ref move_in_wrapper class for a discussion of
1335 * moving values.)
1337 * @par Usage
1338 * A move_in() call to initialize a reducer is often paired with a
1339 * move_out() call to get its final value:
1341 * reducer<Type> xr;
1342 * xr.move_in(x);
1343 * … do the reduction …
1344 * xr.move_out(x);
1346 * @par Assumptions
1347 * - You cannot assume either that this will function will copy its
1348 * value or that it will move it.
1349 * - You must assume that the value of the reducer’s accumulator
1350 * variable will be undefined after the call to move_out().
1351 * - You can assume that move_out() will be at least as efficient as
1352 * get_value(), and you should therefore prefer move_out() unless
1353 * you need the accumulator variable to be preserved after the
1354 * call.
1356 * @warning Calling this function other than to retrieve the final
1357 * value of a reduction will almost always result in undefined
1358 * behavior.
1360 * @param obj The object that the value of the reducer will be moved into.
1362 * @post @a obj contains the value that was initially in the reducer.
1363 * @post The value of the reducer is undefined.
1365 * @see get_value()
1367 void move_out(value_type& obj) { set_get::move_out(view(), obj); }
1369 /** Set the value of the reducer.
1371 * This function sets the initial value of the reducer’s accumulator
1372 * variable to the value of @a obj.
1374 * @note The behavior of a default constructor followed by
1375 * initialization:
1377 * reducer<Type> xr;
1378 * xr.set_value(x);
1380 * @note is not necessarily the same as a value constructor:
1382 * reducer<Type> xr(x);
1384 * @note In particular, when @a Type is a container type with a
1385 * non-empty allocator, the value constructor will create the
1386 * accumulator variable with the same allocator as the input
1387 * argument @a x, while the default constructor will create the
1388 * accumulator variable with a default allocator.
1390 * @warning Calling this function other than to set the initial value
1391 * for a reduction will almost always result in undefined
1392 * behavior.
1394 * @param obj The object containing the value that will be copied into
1395 * the reducer.
1397 * @post The reducer contains a copy of the value in @a obj.
1399 * @see move_in()
1401 void set_value(const value_type& obj) { set_get::set_value(view(), obj); }
1403 /** Get the value of the reducer.
1405 * This function gets the final value of the reducer’s accumulator
1406 * variable.
1408 * @warning Calling this function other than to retrieve the final
1409 * value of a reduction will almost always result in undefined
1410 * behavior.
1412 * @return A reference to the value contained in the reducer.
1414 * @see move_out()
1416 typename set_get::get_value_type get_value() const
1417 { return set_get::get_value(view()); }
1419 //@}
1421 /** Implicit downcast to legacy reducer wrapper, if any.
1423 * @see legacy_reducer_downcast
1425 operator typename legacy_reducer_downcast<reducer>::type& ()
1427 typedef typename legacy_reducer_downcast<reducer>::type downcast_type;
1428 return *reinterpret_cast<downcast_type*>(this);
1432 /** Implicit downcast to legacy reducer wrapper, if any.
1434 * @see legacy_reducer_downcast
1436 operator const typename legacy_reducer_downcast<reducer>::type& () const
1438 typedef typename legacy_reducer_downcast<reducer>::type downcast_type;
1439 return *reinterpret_cast<const downcast_type*>(this);
1443 #ifdef CILK_STUB
1444 } // namespace stub
1445 using stub::reducer;
1446 #endif
1448 } // end namespace cilk
1450 #endif /* __cplusplus */
1452 /** @page page_reducers_in_c Creating and Using Reducers in C
1454 * @tableofcontents
1456 * The Cilk runtime supports reducers written in C as well as in C++. The basic logic is the
1457 * same, but the implementation details are very different. The C++ reducer implementation uses
1458 * templates heavily to create very generic components. The C reducer implementation uses
1459 * macros, which are a much blunter instrument. The most immediate consequence is that the
1460 * monoid/view/reducer architecture is mostly implicit rather than explicit in C reducers.
1462 * @section reducers_c_overview Overview of Using Reducers in C
1464 * The basic usage pattern for C reducers is:
1466 * 1. Create and initialize a reducer object.
1467 * 2. Tell the Cilk runtime about the reducer.
1468 * 3. Update the value contained in the reducer in a parallel computation.
1469 * 4. Tell the Cilk runtime that you are done with the reducer.
1470 * 5. Retrieve the value from the reducer.
1472 * @subsection reducers_c_creation Creating and Initializing a C Reducer
1474 * The basic pattern for creating and initializing a reducer object in C is
1476 * CILK_C_DECLARE_REDUCER(value-type) reducer-name =
1477 * CILK_C_INIT_REDUCER(value-type,
1478 * reduce-function,
1479 * identity-function,
1480 * destroy-function,
1481 * initial-value);
1483 * This is simply an initialized definition of a variable named _reducer-name_. The
1484 * @ref CILK_C_DECLARE_REDUCER macro expands to an anonymous `struct` declaration for a reducer
1485 * object containing a view of type _value-type_, and the @ref CILK_C_INIT_REDUCER macro
1486 * expands to a struct initializer.
1488 * @subsection reducers_c_reduce_func Reduce Functions
1490 * The reduce function for a reducer is called when a parallel execution strand terminates, to
1491 * combine the values computed by the terminating strand and the strand to its left. It takes
1492 * three arguments:
1494 * - `void* reducer` — the address of the reducer.
1495 * - `void* left` — the address of the value for the left strand.
1496 * - `void* right` — the address of the value for the right (terminating) strand.
1498 * It must apply the reducer’s reduction operation to the `left` and `right` values, leaving
1499 * the result in the `left` value. The `right` value is undefined after the reduce function
1500 * call.
1502 * @subsection reducers_c_identity_func Identity Functions
1504 * The identity function for a reducer is called when a parallel execution strand begins, to
1505 * initialize its value to the reducer’s identity value. It takes two arguments:
1507 * - `void* reducer` — the address of the reducer.
1508 * - `void* v` — the address of a freshly allocated block of memory of size
1509 * `sizeof(value-type)`.
1511 * It must initialize the memory pointed to by `v` so that it contains the reducer’s identity
1512 * value.
1514 * @subsection reducers_c_destroy_func Destroy Functions
1516 * The destroy function for a reducer is called when a parallel execution strand terminates, to
1517 * do any necessary cleanup before its value is deallocated. It takes two arguments:
1519 * - `void* reducer` — the address of the reducer.
1520 * - `void* p` — the address of the value for the terminating strand.
1522 * It must release any resources belonging to the value pointed to by `p`, to avoid a resource
1523 * leak when the memory containing the value is deallocated.
1525 * The runtime function `__cilkrts_hyperobject_noop_destroy` can be used for the destructor
1526 * function if the reducer’s values do not need any cleanup.
1528 * @subsection reducers_c_register Tell the Cilk Runtime About the Reducer
1530 * Call the @ref CILK_C_REGISTER_REDUCER macro to register the reducer with the Cilk runtime:
1532 * CILK_C_REGISTER_REDUCER(reducer-name);
1534 * The runtime will manage reducer values for all registered reducers when parallel execution
1535 * strands begin and end.
1537 * @subsection reducers_c_update Update the Value Contained in the Reducer
1539 * The @ref REDUCER_VIEW macro returns a reference to the reducer’s value for the current
1540 * parallel strand:
1542 * REDUCER_VIEW(reducer-name) = REDUCER_VIEW(reducer-name) OP x;
1544 * C++ reducer views restrict access to the wrapped value so that it can only be modified in
1545 * ways consistent with the reducer’s operation. No such protection is provided for C reducers.
1546 * It is
1547 * entirely the responsibility of the user to avoid modifying the value in any
1548 * inappropriate way.
1550 * @subsection c_reducers_unregister Tell the Cilk Runtime That You Are Done with the Reducer
1552 * When the parallel computation is complete, call the @ref CILK_C_UNREGISTER_REDUCER macro to
1553 * unregister the reducer with the Cilk runtime:
1555 * CILK_C_UNREGISTER_REDUCER(reducer-name);
1557 * The runtime will stop managing reducer values for the reducer.
1559 * @subsection c_reducers_retrieve Retrieve the Value from the Reducer
1561 * When the parallel computation is complete, use the @ref REDUCER_VIEW macro to retrieve the
1562 * final value computed by the reducer.
1564 * @subsection reducers_c_example_custom Example — Creating and Using a Custom C Reducer
1566 * The `IntList` type represents a simple list of integers.
1568 * struct _intListNode {
1569 * int value;
1570 * _intListNode* next;
1571 * } IntListNode;
1572 * typedef struct { IntListNode* head; IntListNode* tail; } IntList;
1574 * // Initialize a list to be empty
1575 * void IntList_init(IntList* list) { list->head = list->tail = 0; }
1577 * // Append an integer to the list
1578 * void IntList_append(IntList* list, int x)
1579 * {
1580 * IntListNode* node = (IntListNode*) malloc(sizeof(IntListNode));
1581 * if (list->tail) list->tail->next = node; else list->head = node;
1582 * list->tail = node;
1585 * // Append the right list to the left list, and leave the right list empty
1586 * void IntList_concat(IntList* left, IntList* right)
1588 * if (left->head) {
1589 * left->tail->next = right->head;
1590 * if (right->tail) left->tail = right->tail;
1592 * else {
1593 * *left = *right;
1595 * IntList_init(*right);
1598 * This code creates a reducer that supports creating an `IntList` by appending values to it.
1600 * void identity_IntList(void* reducer, void* list)
1602 * IntList_init((IntList*)list);
1605 * void reduce_IntList(void* reducer, void* left, void* right)
1607 * IntList_concat((IntList*)left, (IntList*)right);
1610 * CILK_C_DECLARE_REDUCER(IntList) my_list_int_reducer =
1611 * CILK_C_INIT_REDUCER(IntList,
1612 * reduce_int_list,
1613 * identity_int_list,
1614 * __cilkrts_hyperobject_noop_destroy);
1615 * // Initial value omitted //
1616 * ListInt_init(&REDUCER_VIEW(my_int_list_reducer));
1618 * CILK_C_REGISTER_REDUCER(my_int_list_reducer);
1619 * cilk_for (int i = 0; i != n; ++i) {
1620 * IntList_append(&REDUCER_VIEW(my_int_list_reducer), a[i]);
1622 * CILK_C_UNREGISTER_REDUCER(my_int_list_reducer);
1624 * IntList result = REDUCER_VIEW(my_int_list_reducer);
1626 * @section reducers_c_predefined Predefined C Reducers
1628 * Some of the predefined reducer classes in the Cilk library come with a set of predefined
1629 * macros to provide the same capabilities in C. In general, two macros are provided for each
1630 * predefined reducer family:
1632 * - `CILK_C_REDUCER_operation(reducer-name, type-name, initial-value)` — Declares a
1633 * reducer object named _reducer-name_ with initial value _initial-value_ to perform
1634 * a reduction using the _operation_ on values of the type specified by _type-name_.
1635 * This is the equivalent of the general code described in @ref reducers_c_creation :
1637 * CILK_C_DECLARE_REDUCER(type) reducer-name =
1638 * CILK_C_INIT_REDUCER(type, ..., initial-value);
1640 * where _type_ is the C type corresponding to _type_name_. See @ref reducers_c_type_names
1641 * below for the _type-names_ that you can use.
1643 * - `CILK_C_REDUCER_operation_TYPE(type-name)` — Expands to the `typedef` name for the type
1644 * of the reducer object declared by
1645 * `CILK_C_REDUCER_operation(reducer-name, type-name, initial-value)`.
1647 * See @ref reducers_c_example_predefined.
1649 * The predefined C reducers are:
1651 * | Operation | Name | Documentation |
1652 * |-------------------|---------------|-------------------------------|
1653 * | addition | `OPADD` | @ref ReducersAdd |
1654 * | bitwise and | `OPAND` | @ref ReducersAnd |
1655 * | bitwise or | `OPOR` | @ref ReducersOr |
1656 * | bitwise xor | `OPXOR` | @ref ReducersXor |
1657 * | multiplication | `OPMUL` | @ref ReducersMul |
1658 * | minimum | `MIN` | @ref ReducersMinMax |
1659 * | minimum & index | `MIN_INDEX` | @ref ReducersMinMax |
1660 * | maximum | `MIN` | @ref ReducersMinMax |
1661 * | maximum & index | `MIN_INDEX` | @ref ReducersMinMax |
1663 * @subsection reducers_c_type_names Numeric Type Names
1665 * The type and function names created by the C reducer definition macros incorporate both the
1666 * reducer kind (`opadd`, `opxor`, etc.) and the value type of the reducer (`int`, `double`,
1667 * etc.). The value type is represented by a _numeric type name_ string. The types supported
1668 * in C reducers, and their corresponding numeric type names, are given in the following table:
1670 * | Type | Numeric Type Name |
1671 * |-----------------------|-------------------------------|
1672 * | `char` | `char` |
1673 * | `unsigned char` | `uchar` |
1674 * | `signed char` | `schar` |
1675 * | `wchar_t` | `wchar_t` |
1676 * | `short` | `short` |
1677 * | `unsigned short` | `ushort` |
1678 * | `int` | `int` |
1679 * | `unsigned int` | `uint` |
1680 * | `unsigned int` | `unsigned` (alternate name) |
1681 * | `long` | `long` |
1682 * | `unsigned long` | `ulong` |
1683 * | `long long` | `longlong` |
1684 * | `unsigned long long` | `ulonglong` |
1685 * | `float` | `float` |
1686 * | `double` | `double` |
1687 * | `long double` | `longdouble` |
1689 * @subsection reducers_c_example_predefined Example — Using a Predefined C Reducer
1691 * To compute the sum of all the values in an array of `unsigned int`:
1693 * CILK_C_REDUCER_OPADD(sum, uint, 0);
1694 * CILK_C_REGISTER_REDUCER(sum);
1695 * cilk_for(int i = 0; i != n; ++i) {
1696 * REDUCER_VIEW(sum) += a[i];
1698 * CILK_C_UNREGISTER_REDUCER(sum);
1699 * printf("The sum is %u\n", REDUCER_VIEW(sum));
1703 /** @name C language reducer macros
1705 * These macros are used to declare and work with reducers in C code.
1707 * @see @ref page_reducers_in_c
1709 //@{
1711 /// @cond internal
1713 /** @name Compound identifier macros.
1715 * These macros are used to construct an identifier by concatenating two or three identifiers.
1717 //@{
1719 /** Expand to an identifier formed by concatenating two identifiers.
1721 #define __CILKRTS_MKIDENT(a,b) __CILKRTS_MKIDENT_IMP(a,b,)
1723 /** Expand to an identifier formed by concatenating three identifiers.
1725 #define __CILKRTS_MKIDENT3(a,b,c) __CILKRTS_MKIDENT_IMP(a,b,c)
1727 /** Helper macro to do the concatenation.
1729 #define __CILKRTS_MKIDENT_IMP(a,b,c) a ## b ## c
1731 //@}
1733 /** Compiler-specific keyword for the “type of” operator.
1735 #if defined(__GNUC__) && !defined(__INTEL_COMPILER)
1736 # define _Typeof __typeof__
1737 #endif
1739 /** @name Predefined reducer function declaration macros.
1741 * These macros are used to create the function headers for the identity, reduction,
1742 * and destructor functions for a builtin reducer family. The macro can be followed by
1743 * a semicolon to create a declaration, or by a brace-enclosed body to create a definition.
1745 //@{
1747 /** Create an identity function header.
1749 * @note The name of the function’s value pointer parameter will always be `v`.
1751 * @param name The reducer family name.
1752 * @param tn The type name.
1754 #define __CILKRTS_DECLARE_REDUCER_IDENTITY(name,tn) CILK_EXPORT \
1755 void __CILKRTS_MKIDENT3(name,_identity_,tn)(void* key, void* v)
1757 /** Create a reduction function header.
1759 * @param name The reducer family name.
1760 * @param tn The type name.
1761 * @param l The name to use for the function’s left value pointer parameter.
1762 * @param r The name to use for the function’s right value pointer parameter.
1764 #define __CILKRTS_DECLARE_REDUCER_REDUCE(name,tn,l,r) CILK_EXPORT \
1765 void __CILKRTS_MKIDENT3(name,_reduce_,tn)(void* key, void* l, void* r)
1767 /** Create a destructor function header.
1769 * @param name The reducer family name.
1770 * @param tn The type name.
1771 * @param p The name to use for the function’s value pointer parameter.
1773 #define __CILKRTS_DECLARE_REDUCER_DESTROY(name,tn,p) CILK_EXPORT \
1774 void __CILKRTS_MKIDENT3(name,_destroy_,tn)(void* key, void* p)
1776 //@}
1778 /// @endcond
1781 /***************************************************************************
1782 * Real implementation
1783 ***************************************************************************/
1785 /** Declaration of a C reducer structure type.
1787 * This macro expands into an anonymous structure declaration for a C reducer structure
1788 * which contains a @a Type value. For example:
1790 * CILK_C_DECLARE_REDUCER(int) my_add_int_reducer =
1791 * CILK_C_INIT_REDUCER(int, …);
1793 * @param Type The type of the value contained in the reducer object.
1795 * @see @ref reducers_c_creation
1797 #define CILK_C_DECLARE_REDUCER(Type) struct { \
1798 __cilkrts_hyperobject_base __cilkrts_hyperbase; \
1799 __CILKRTS_CACHE_ALIGN Type value; \
1802 /** Initializer for a C reducer structure.
1804 * This macro expands into a brace-enclosed structure initializer for a C reducer structure
1805 * that was declared with `CILK_C_DECLARE_REDUCER(Type)`. For example:
1807 * CILK_C_DECLARE_REDUCER(int) my_add_int_reducer =
1808 * CILK_C_INIT_REDUCER(int,
1809 * add_int_reduce,
1810 * add_int_identity,
1811 * __cilkrts_hyperobject_noop_destroy,
1812 * 0);
1814 * @param Type The type of the value contained in the reducer object. Must be the same as
1815 * the @a Type argument of the CILK_C_DECLARE_REDUCER macro call that created
1816 * the reducer.
1817 * @param Reduce The address of the @ref reducers_c_reduce_func "reduce function" for the
1818 * reducer.
1819 * @param Identity The address of the @ref reducers_c_identity_func "identity function" for
1820 * the reducer.
1821 * @param Destroy The address of the @ref reducers_c_destroy_func "destroy function" for the
1822 * reducer.
1823 * @param ... The initial value for the reducer. (A single expression if @a Type is a
1824 * scalar type; a list of values if @a Type is a struct or array type.)
1826 * @see @ref reducers_c_creation
1829 #define CILK_C_INIT_REDUCER(Type, Reduce, Identity, Destroy, ...) \
1830 { { { Reduce \
1831 , Identity \
1832 , Destroy \
1833 , __cilkrts_hyperobject_alloc \
1834 , __cilkrts_hyperobject_dealloc \
1836 , 0 \
1837 , __CILKRTS_CACHE_LINE__ \
1838 , sizeof(Type) \
1840 , __VA_ARGS__ \
1843 /** Register a reducer with the Cilk runtime.
1845 * The runtime will manage reducer values for all registered reducers when parallel execution
1846 * strands begin and end. For example:
1848 * CILK_C_REGISTER_REDUCER(my_add_int_reducer);
1849 * cilk_for (int i = 0; i != n; ++i) {
1850 * …
1853 * @param Expr The reducer to be registered.
1855 * @see @ref page_reducers_in_c
1857 #define CILK_C_REGISTER_REDUCER(Expr) \
1858 __cilkrts_hyper_create(&(Expr).__cilkrts_hyperbase)
1860 /** Unregister a reducer with the Cilk runtime.
1862 * The runtime will stop managing reducer values for a reducer after it is unregistered. For
1863 * example:
1865 * cilk_for (int i = 0; i != n; ++i) {
1866 * …
1868 * CILK_C_UNREGISTER_REDUCER(my_add_int_reducer);
1870 * @param Expr The reducer to be unregistered.
1872 * @see @ref page_reducers_in_c
1874 #define CILK_C_UNREGISTER_REDUCER(Expr) \
1875 __cilkrts_hyper_destroy(&(Expr).__cilkrts_hyperbase)
1877 /** Get the current view for a reducer.
1879 * The `REDUCER_VIEW(reducer-name)` returns a reference to the reducer’s value for the
1880 * current parallel strand. This can be used to initialize thevalue of the reducer before it
1881 * is used, to modify the value of the reducer on the current parallel strand, or to retrieve
1882 * the final value of the reducer at the end of the parallel computation.
1884 * REDUCER_VIEW(my_add_int_reducer) = REDUCER_VIEW(my_add_int_reducer) + x;
1886 * @note C++ reducer views restrict access to the wrapped value so that it can only be
1887 * modified in ways consistent with the reducer’s operation. No such protection is provided
1888 * for C reducers. It is entirely the responsibility of the user to refrain from modifying the
1889 * value in any inappropriate way.
1891 * @param Expr The reducer whose value is to be returned.
1893 * @see @ref page_reducers_in_c
1895 #define REDUCER_VIEW(Expr) (*(_Typeof((Expr).value)*) \
1896 __cilkrts_hyper_lookup(&(Expr).__cilkrts_hyperbase))
1898 //@} C language reducer macros
1900 #endif // CILK_REDUCER_H_INCLUDED