Base subreg rules on REGMODE_NATURAL_SIZE rather than UNITS_PER_WORD
[official-gcc.git] / libcilkrts / include / cilk / reducer_ostream.h
blob793c3c5020cdf79df0a558018de930e3c83eebae
1 /* reducer_ostream.h -*- C++ -*-
3 * Copyright (C) 2009-2016, Intel Corporation
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in
14 * the documentation and/or other materials provided with the
15 * distribution.
16 * * Neither the name of Intel Corporation nor the names of its
17 * contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
27 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
30 * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
33 * *********************************************************************
35 * PLEASE NOTE: This file is a downstream copy of a file mainitained in
36 * a repository at cilkplus.org. Changes made to this file that are not
37 * submitted through the contribution process detailed at
38 * http://www.cilkplus.org/submit-cilk-contribution will be lost the next
39 * time that a new version is released. Changes only submitted to the
40 * GNU compiler collection or posted to the git repository at
41 * https://bitbucket.org/intelcilkruntime/intel-cilk-runtime.git are
42 * not tracked.
44 * We welcome your contributions to this open source project. Thank you
45 * for your assistance in helping us improve Cilk Plus.
48 /** @file reducer_ostream.h
50 * @brief Defines a class for writing to an ostream in parallel.
52 * @ingroup ReducersOstream
54 * @see @ref ReducersOstream
57 #ifndef REDUCER_OSTREAM_H_INCLUDED
58 #define REDUCER_OSTREAM_H_INCLUDED
60 #include <cilk/reducer.h>
61 #include <ostream>
62 #include <sstream>
64 /** @defgroup ReducersOstream Ostream Reducers
66 * Ostream reducers allow multiple strands to write to an ostream in parallel.
68 * @ingroup Reducers
70 * You should be familiar with @ref pagereducers "Intel(R) Cilk(TM) Plus reducers",
71 * described in file reducers.md, and particularly with @ref reducers_using,
72 * before trying to use the information in this file.
74 * @section redostream_usage Usage Example
76 * One of the most common debugging techniques is adding `print` statements
77 * to the code being debugged. When the code is parallelized, the results can
78 * be less than satisfactory, as output from multiple strands is mingled in an
79 * unpredictable way. Like other reducers, an ostream reducer requires minimal
80 * recoding to guarantee that the output from parallelized computation will be
81 * ordered the same as though the computation were executed serially.
83 * cilk::reducer<cilk::op_ostream> r(std::cerr);
84 * cilk_for (int i = 0; i != data.size(); ++i) {
85 * *r << "Iteration " << i << ":\n";
86 * ... some computation ...
87 * *r << " Step 1:" << some information;
88 * ... some more computation ...
89 * *r << " Step 2:" << some more information;
90 * ... still more computation ...
91 * *r << " Step 3:" << still more information;
92 * }
94 * Output on standard error:
96 * Iteration 1:
97 * Step 1: ...
98 * Step 2: ...
99 * Step 3: ...
100 * Iteration 2:
101 * Step 1: ...
102 * Step 2: ...
103 * Step 3: ...
104 * Iteration 3:
105 * Step 1: ...
106 * Step 2: ...
107 * Step 3: ...
108 * ...
110 * @section redostream_overview Overview
112 * An "ostream reducer" is not really a reducer. It uses the reducer
113 * technology to coordinate operations on parallel strands to achieve
114 * the same behavior in a parallel computation that would be seen in a
115 * serial computation, but it does not have a monoid. It has a "monoid
116 * class," because that is part of the implementation framework, but it
117 * does not represent a mathematical monoid: there is no value type, no
118 * associative operation, and no identity value. The reducer is used for
119 * its side effect rather than to construct a value.
121 * You might think of an ostream reducer as a relative of a
122 * @ref ReducersString "string reducer" which uses stream output
123 * syntax (`stream << value`) instead of string append syntax
124 * (`string += value`), and which writes its result string to an
125 * ostream instead of making it available as the reducer value.
127 * Another difference is that "real" reducers protect their contained
128 * value quite strongly from improper access by the user. Ostream reducers,
129 * on the other hand, pretty much have to expose the ostream, since normal
130 * use of an ostream involves accessing its internal state. Furthermore,
131 * the ostream reducer just coordinates output to an existing ostream -
132 * there is nothing to keep the user from writing directly to the attached
133 * stream, with unpredictable results.
135 * @section redostream_operations Operations
137 * In the operation descriptions below, the type name `Ostream` refers to the
138 * reducer's ostream type, `std::basic_ostream<Char, Traits>`.
140 * @subsection redostream_constructors Constructors
142 * The only constructor is
144 * reducer(const Ostream& os)
146 * This creates a reducer that is associated with the existing ostream `os`.
147 * Anything "written to" the reducer will (eventually) be written to `os`.
149 * @subsection redostream_get_set Set and Get
151 * Just as a stream does not have a "value," neither does an ostream
152 * reducer. Therefore, none of the usual `set_value`, `get_value`,
153 * `move_in`, or `move_out` functions are available for ostream reducers.
155 * @subsection redostream_initial Initial Values
157 * Ostream reducers do not have default constructors.
159 * @subsection redostream_view_ops View Operations
161 * An ostream reducer view is actually a kind of `std::ostream`. Therefore,
162 * any operation that can be used on an ostream can be used on an ostream
163 * reducer view. For example:
165 * reducer<op_ostream> r(cout);
166 * *r << setw(5) << (x=1) << endl;
169 * @section redostream_performance Performance Considerations
171 * Ostream reducers work by creating a string stream for each non-leftmost
172 * view. When two strands are merged, the contents of the string buffer of the
173 * right view are written to the left view. Since all non-leftmost strands are
174 * eventually merged, all output is eventually written to the associated
175 * ostream.
177 * This implementation has two consequences.
179 * First, all output written to an ostream reducer on a stolen strand is kept
180 * in memory (in a string buffer) until the strand is merged with the leftmost
181 * strand. This means that some portion of the output written to an ostream
182 * reducer during a parallel computation - half of the total output, on
183 * average - will temporarily be held in memory during the computation.
184 * Obviously, ostream reducers will work better for small and moderate amounts
185 * of output.
187 * Second, buffered ostream reducer content must be copied at every merge.
188 * The total amount of copying is potentially proportional to the total amount
189 * of output multiplied by the number of strands stolen during the computation.
191 * In short, writing to an ostream in a parallel computation with an ostream
192 * reducer will always be less efficient than writing the same output directly
193 * to the ostream in a serial computation. The value of the ostream
194 * reducer is not in the writing of the ostream itself, but in removing the
195 * race and serialization obstacles that the ostream output would cause in an
196 * otherwise parallelizable computation.
199 * @section redostream_state Stream State
201 * The reducer implementation can correctly order the output that is written
202 * to an ostream. However, an ostream has additional state that controls its
203 * behavior, such as its formatting attributes, error state, extensible arrays, * and registered callbacks. If these are modified during the computation, the * reducer implementation cannot guarantee that they will be the same in a
204 * parallel computation as in a serial computation. In particular:
206 * - In the serial execution, the ostream state in the continuation of a
207 * spawn will be the same as the state at the end of the spawned function.
208 * In the parallel execution, if the continuation is stolen, its view will
209 * contain a newly created ostream with the default initial state.
210 * - In the serial execution, the ostream state following a sync is the same
211 * as the state before the sync. In the parallel execution, if the
212 * continuation is stolen, then the state following the sync will be the
213 * same as the state at the end of some spawned function.
215 * In short, you must not make any assumptions about the stream state of an
216 * ostream reducer:
218 * - Following a `cilk_spawn`.
219 * - Following a `cilk_sync`.
220 * - At the start of an iteration of a `cilk_for` loop.
221 * - Following the completion of a `cilk_for` loop.
223 * @section redostream_types Type and Operator Requirements
225 * `std::basic_ostream<Char, Traits>` must be a valid type.
228 namespace cilk {
230 /** @ingroup ReducersOstream */
231 //@{
233 /** The ostream reducer view class.
235 * This is the view class for reducers created with
236 * `cilk::reducer< cilk::op_basic_ostream<Char, Traits> >`. It holds the
237 * actual ostream for a parallel strand, and allows only stream output
238 * operations to be performed on it.
240 * @note The reducer "dereference" operation (`reducer::operator *()`)
241 * yields a reference to the view. Thus, for example, the view
242 * class's `<<` operation would be used in an expression like
243 * `*r << "x = " << x`, where `r` is an ostream reducer.
245 * @tparam Char The ostream element type (not the ostream type).
246 * @tparam Traits The character traits type.
248 * @see ReducersOstream
249 * @see op_basic_ostream
251 template<typename Char, typename Traits>
252 class op_basic_ostream_view : public std::basic_ostream<Char, Traits>
254 typedef std::basic_ostream<Char, Traits> base;
255 typedef std::basic_ostream<Char, Traits> ostream_type;
257 // A non-leftmost view is associated with a private string buffer. (The
258 // leftmost view is associated with the buffer of the reducer's associated
259 // ostream, so its private buffer is unused.)
261 std::basic_stringbuf<Char, Traits> m_buffer;
263 public:
265 /** Value type. Required by @ref monoid_with_view.
267 typedef ostream_type value_type;
269 /** Reduce operation. Required by @ref monoid_with_view.
271 void reduce(op_basic_ostream_view* other)
273 // Writing an empty buffer results in failure. Testing `sgetc()` is the
274 // easiest way of checking for an empty buffer.
275 if (other->m_buffer.sgetc() != Traits::eof()) {
276 *this << (&other->m_buffer);
280 /** Non-leftmost (identity) view constructor. The view is associated with
281 * its internal buffer. Required by @ref monoid_base.
283 op_basic_ostream_view() : base(&m_buffer) {}
285 /** Leftmost view constructor. The view is associated with an existing
286 * ostream.
288 op_basic_ostream_view(const ostream_type& os) : base(0)
290 base::rdbuf(os.rdbuf()); // Copy stream buffer
291 base::flags(os.flags()); // Copy formatting flags
292 base::setstate(os.rdstate()); // Copy error state
295 /** Sets/gets.
297 * These are all no-ops.
299 //@{
301 void view_set_value(const value_type&)
302 { assert("set_value() is not allowed on ostream reducers" && 0); }
303 const value_type& view_get_value() const
304 { assert("get_value() is not allowed on ostream reducers" && 0);
305 return *this; }
306 typedef value_type const& return_type_for_get_value;
307 void view_move_in(const value_type&)
308 { assert("move_in() is not allowed on ostream reducers" && 0); }
309 void view_move_out(const value_type&)
310 { assert("move_out() is not allowed on ostream reducers" && 0); }
312 //@}
315 /** Ostream monoid class. Instantiate the cilk::reducer template class with an
316 * op_basic_ostream monoid to create an ostream reducer class:
318 * cilk::reducer< cilk::op_basic_string<char> > r;
320 * @tparam Char The stream element type (not the stream type).
321 * @tparam Traits The character traits type.
323 * @see ReducersOstream
324 * @see op_basic_ostream_view
325 * @see reducer_ostream
326 * @see op_ostream
327 * @see op_wostream
329 template<typename Char,
330 typename Traits = std::char_traits<Char>,
331 bool Align = false>
332 class op_basic_ostream :
333 public monoid_with_view< op_basic_ostream_view<Char, Traits>, Align >
335 typedef monoid_with_view< op_basic_ostream_view<Char, Traits>, Align >
336 base;
337 typedef std::basic_ostream<Char, Traits> ostream_type;
338 typedef provisional_guard<typename base::view_type> view_guard;
340 public:
342 /** View type of the monoid.
344 typedef typename base::view_type view_type;
346 /** @name Construct function.
348 * The only supported ostream reducer constructor takes a reference to
349 * an existing ostream.
351 * @param os The ostream destination for receive all data written to the
352 * reducer.
354 static void construct(
355 op_basic_ostream* monoid,
356 view_type* view,
357 const ostream_type& os)
359 view_guard vg( new((void*) view) view_type(os) );
360 vg.confirm_if( new((void*) monoid) op_basic_ostream );
366 * Convenience typedef for narrow ostreams.
368 typedef op_basic_ostream<char> op_ostream;
371 * Convenience typedef for wide ostreams.
373 typedef op_basic_ostream<wchar_t> op_wostream;
375 /// @cond internal
377 class reducer_ostream;
379 /** Metafunction specialization for reducer conversion.
381 * This specialization of the @ref legacy_reducer_downcast template class
382 * defined in reducer.h causes the `reducer<op_basic_ostream<char> >` class
383 * to have an `operator reducer_ostream& ()` conversion operator that
384 * statically downcasts the `reducer<op_basic_ostream<char> >` to
385 * `reducer_ostream`. (The reverse conversion, from `reducer_ostream` to
386 * `reducer<op_basic_ostream<char> >`, is just an upcast, which is provided
387 * for free by the language.)
389 template<bool Align>
390 struct legacy_reducer_downcast<
391 reducer<op_basic_ostream<char, std::char_traits<char>, Align> > >
393 typedef reducer_ostream type;
396 /// @endcond
398 /** Deprecated ostream reducer class.
400 * reducer_ostream is the same as @ref cilk::reducer<@ref op_ostream>, except
401 * that reducer_ostream is a proxy for the contained view, so that ostream
402 * operations can be applied directly to the reducer. For example, a number is
403 * written to a `reducer<op_ostream>` with `*r << x`, but a number can be
404 * written to a `reducer_ostream` with `r << x`.
406 * @deprecated Users are strongly encouraged to use `reducer<monoid>`
407 * reducers rather than the old wrappers like reducer_ostream. The
408 * `reducer<monoid>` reducers show the reducer/monoid/view
409 * architecture more clearly, are more consistent in their
410 * implementation, and present a simpler model for new
411 * user-implemented reducers.
413 * @note Implicit conversions are provided between `%reducer_ostream`
414 * and `reducer<%op_ostream>`. This allows incremental code
415 * conversion: old code that used `%reducer_ostream` can pass a
416 * `%reducer_ostream` to a converted function that now expects a
417 * pointer or reference to a `reducer<%op_ostream>`, and vice versa.
419 * @tparam Char The stream element type (not the stream type).
420 * @tparam Traits The character traits type.
422 * @see op_ostream
423 * @see reducer
424 * @see ReducersOstream
426 class reducer_ostream :
427 public reducer<op_basic_ostream<char, std::char_traits<char>, true> >
429 typedef reducer<op_basic_ostream<char, std::char_traits<char>, true> > base;
430 using base::view;
431 public:
433 /// The view type for the reducer.
434 typedef base::view_type View;
436 /// The monoid type for the reducer.
437 typedef base::monoid_type Monoid;
439 /** Constructs an initial `reducer_ostream` from a `std::ostream`. The
440 * specified stream is used as the eventual destination for all text
441 * streamed to this hyperobject.
443 explicit reducer_ostream(const std::ostream &os) : base(os) {}
445 /** Returns a modifiable reference to the underlying 'ostream' object.
447 std::ostream& get_reference() { return view(); }
449 /** Writes to the ostream.
451 template<typename T>
452 std::ostream& operator<< (const T &v)
454 return view() << v;
458 * Calls a manipulator.
460 * @param _Pfn Pointer to the manipulator function.
462 reducer_ostream& operator<< (std::ostream &(*_Pfn)(std::ostream &))
464 (*_Pfn)(view());
465 return *this;
468 /** @name Dereference
469 * @details Dereferencing a wrapper is a no-op. It simply returns the
470 * wrapper. Combined with the rule that the wrapper forwards view
471 * operations to its contained view, this means that view operations can
472 * be written the same way on reducers and wrappers, which is convenient
473 * for incrementally converting old code using wrappers to use reducers
474 * instead. That is:
476 * reducer<op_ostream> r;
477 * *r << "a"; // *r returns the view
478 * // operator<<() is a view member function
480 * reducer_ostream w;
481 * *w << "a"; // *w returns the wrapper
482 * // operator<<() is a wrapper member function
483 * // that calls the corresponding view function
485 //@{
486 reducer_ostream& operator*() { return *this; }
487 reducer_ostream const& operator*() const { return *this; }
489 reducer_ostream* operator->() { return this; }
490 reducer_ostream const* operator->() const { return this; }
491 //@}
493 /** @name Upcast
494 * @details In Intel Cilk Plus library 0.9, reducers were always cache-aligned.
495 * In library 1.0, reducer cache alignment is optional. By default,
496 * reducers are unaligned (i.e., just naturally aligned), but legacy
497 * wrappers inherit from cache-aligned reducers for binary compatibility.
499 * This means that a wrapper will automatically be upcast to its aligned
500 * reducer base class. The following conversion operators provide
501 * pseudo-upcasts to the corresponding unaligned reducer class.
503 //@{
504 operator reducer<op_ostream>& ()
506 return *reinterpret_cast< reducer<op_ostream>* >(this);
508 operator const reducer<op_ostream>& () const
510 return *reinterpret_cast< const reducer<op_ostream>* >(this);
512 //@}
515 } // namespace cilk
517 #endif // REDUCER_OSTREAM_H_INCLUDED