ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/jsr166y/CountedCompleter.java
(Generate patch)

Comparing jsr166/src/jsr166y/CountedCompleter.java (file contents):
Revision 1.2 by dl, Sat Apr 21 11:45:20 2012 UTC vs.
Revision 1.5 by jsr166, Sun Oct 21 05:28:08 2012 UTC

# Line 7 | Line 7
7   package jsr166y;
8  
9   /**
10 < * A resultless {@link ForkJoinTask} with a completion action
10 > * A {@link ForkJoinTask} with a completion action
11   * performed when triggered and there are no remaining pending
12   * actions. Uses of CountedCompleter are similar to those of other
13   * completion based components (such as {@link
# Line 22 | Line 22 | package jsr166y;
22   * decremented; otherwise, the completion action is performed, and if
23   * this completer itself has a completer, the process is continued
24   * with its completer.  As is the case with related synchronization
25 < * components such as {@link Phaser} and {@link
26 < * java.util.concurrent.Semaphore} these methods affect only internal
27 < * counts; they do not establish any further internal bookkeeping. In
28 < * particular, the identities of pending tasks are not maintained. As
29 < * illustrated below, you can create subclasses that do record some or
30 < * all pended tasks or their results when needed.
25 > * components such as {@link java.util.concurrent.Phaser Phaser} and
26 > * {@link java.util.concurrent.Semaphore Semaphore}, these methods
27 > * affect only internal counts; they do not establish any further
28 > * internal bookkeeping. In particular, the identities of pending
29 > * tasks are not maintained. As illustrated below, you can create
30 > * subclasses that do record some or all pending tasks or their
31 > * results when needed.
32   *
33   * <p>A concrete CountedCompleter class must define method {@link
34   * #compute}, that should, in almost all use cases, invoke {@code
# Line 36 | Line 37 | package jsr166y;
37   * normal completion, and method {@link #onExceptionalCompletion} to
38   * perform an action upon any exception.
39   *
40 + * <p>CountedCompleters most often do not bear results, in which case
41 + * they are normally declared as {@code CountedCompleter<Void>}, and
42 + * will always return {@code null} as a result value.  In other cases,
43 + * you should override method {@link #getRawResult} to provide a
44 + * result from {@code join(), invoke()}, and related methods. (Method
45 + * {@link #setRawResult} by default plays no role in CountedCompleters
46 + * but may be overridden for example to maintain fields holding result
47 + * data.)
48 + *
49   * <p>A CountedCompleter that does not itself have a completer (i.e.,
50   * one for which {@link #getCompleter} returns {@code null}) can be
51   * used as a regular ForkJoinTask with this added functionality.
# Line 55 | Line 65 | package jsr166y;
65   * <p><b>Parallel recursive decomposition.</b> CountedCompleters may
66   * be arranged in trees similar to those often used with {@link
67   * RecursiveAction}s, although the constructions involved in setting
68 < * them up typically vary. Even though they entail a bit more
68 > * them up typically vary. Here, the completer of each task is its
69 > * parent in the computation tree. Even though they entail a bit more
70   * bookkeeping, CountedCompleters may be better choices when applying
71   * a possibly time-consuming operation (that cannot be further
72   * subdivided) to each element of an array or collection; especially
# Line 80 | Line 91 | package jsr166y;
91   * <pre> {@code
92   * class MyOperation<E> { void apply(E e) { ... }  }
93   *
94 < * class ForEach<E> extends CountedCompleter {
94 > * class ForEach<E> extends CountedCompleter<Void> {
95   *
96   *     public static <E> void forEach(ForkJoinPool pool, E[] array, MyOperation<E> op) {
97   *         pool.invoke(new ForEach<E>(null, array, op, 0, array.length));
98   *     }
99   *
100   *     final E[] array; final MyOperation<E> op; final int lo, hi;
101 < *     ForEach(CountedCompleter p, E[] array, MyOperation<E> op, int lo, int hi) {
101 > *     ForEach(CountedCompleter<?> p, E[] array, MyOperation<E> op, int lo, int hi) {
102   *         super(p);
103   *         this.array = array; this.op = op; this.lo = lo; this.hi = hi;
104   *     }
# Line 162 | Line 173 | package jsr166y;
173   * and reductions are all of type {@code E}), one way to do this in
174   * divide and conquer designs is to have each subtask record its
175   * sibling, so that it can be accessed in method {@code onCompletion}.
176 < * For clarity, this class uses explicit left and right subtasks, but
177 < * variants of other streamlinings seen in the above example may also
178 < * apply.
176 > * This technique applies to reductions in which the order of
177 > * combining left and right results does not matter; ordered
178 > * reductions require explicit left/right designations.  Variants of
179 > * other streamlinings seen in the above examples may also apply.
180   *
181   * <pre> {@code
182   * class MyMapper<E> { E apply(E v) {  ...  } }
183   * class MyReducer<E> { E apply(E x, E y) {  ...  } }
184 < * class MapReducer<E> extends CountedCompleter {
184 > * class MapReducer<E> extends CountedCompleter<E> {
185   *     final E[] array; final MyMapper<E> mapper;
186   *     final MyReducer<E> reducer; final int lo, hi;
187 < *     MapReducer sibling;
187 > *     MapReducer<E> sibling;
188   *     E result;
189   *     MapReducer(CountedCompleter p, E[] array, MyMapper<E> mapper,
190   *                MyReducer<E> reducer, int lo, int hi) {
# Line 207 | Line 219 | package jsr166y;
219   *                result = reducer.apply(child.result, sib.result);
220   *         }
221   *     }
222 + *     public E getRawResult() { return result; }
223   *
224   *     public static <E> E mapReduce(ForkJoinPool pool, E[] array,
225   *                                   MyMapper<E> mapper, MyReducer<E> reducer) {
226 < *         MapReducer<E> mr = new MapReducer<E>(null, array, mapper,
227 < *                                              reducer, 0, array.length);
215 < *         pool.invoke(mr);
216 < *         return mr.result;
226 > *         return pool.invoke(new MapReducer<E>(null, array, mapper,
227 > *                                              reducer, 0, array.length));
228   *     }
229   * } }</pre>
230   *
# Line 223 | Line 234 | package jsr166y;
234   * triggers another async task. For example:
235   *
236   * <pre> {@code
237 < * class HeaderBuilder extends CountedCompleter { ... }
238 < * class BodyBuilder extends CountedCompleter { ... }
239 < * class PacketSender extends CountedCompleter {
237 > * class HeaderBuilder extends CountedCompleter<...> { ... }
238 > * class BodyBuilder extends CountedCompleter<...> { ... }
239 > * class PacketSender extends CountedCompleter<...> {
240   *     PacketSender(...) { super(null, 1); ... } // trigger on second completion
241   *     public void compute() { } // never called
242 < *     public void onCompletion(CountedCompleter caller) { sendPacket(); }
242 > *     public void onCompletion(CountedCompleter<?> caller) { sendPacket(); }
243   * }
244   * // sample use:
245   * PacketSender p = new PacketSender();
# Line 239 | Line 250 | package jsr166y;
250   * @since 1.8
251   * @author Doug Lea
252   */
253 < public abstract class CountedCompleter extends ForkJoinTask<Void> {
253 > public abstract class CountedCompleter<T> extends ForkJoinTask<T> {
254      private static final long serialVersionUID = 5232453752276485070L;
255  
256      /** This task's completer, or null if none */
257 <    final CountedCompleter completer;
257 >    final CountedCompleter<?> completer;
258      /** The number of pending tasks until completion */
259      volatile int pending;
260  
# Line 254 | Line 265 | public abstract class CountedCompleter e
265       * @param completer this tasks completer, or {@code null} if none
266       * @param initialPendingCount the initial pending count
267       */
268 <    protected CountedCompleter(CountedCompleter completer,
268 >    protected CountedCompleter(CountedCompleter<?> completer,
269                                 int initialPendingCount) {
270          this.completer = completer;
271          this.pending = initialPendingCount;
# Line 266 | Line 277 | public abstract class CountedCompleter e
277       *
278       * @param completer this tasks completer, or {@code null} if none
279       */
280 <    protected CountedCompleter(CountedCompleter completer) {
280 >    protected CountedCompleter(CountedCompleter<?> completer) {
281          this.completer = completer;
282      }
283  
# Line 292 | Line 303 | public abstract class CountedCompleter e
303       * @param caller the task invoking this method (which may
304       * be this task itself).
305       */
306 <    public void onCompletion(CountedCompleter caller) {
306 >    public void onCompletion(CountedCompleter<?> caller) {
307      }
308  
309      /**
# Line 312 | Line 323 | public abstract class CountedCompleter e
323       * @return true if this exception should be propagated to this
324       * tasks completer, if one exists.
325       */
326 <    public boolean onExceptionalCompletion(Throwable ex, CountedCompleter caller) {
326 >    public boolean onExceptionalCompletion(Throwable ex, CountedCompleter<?> caller) {
327          return true;
328      }
329  
# Line 322 | Line 333 | public abstract class CountedCompleter e
333       *
334       * @return the completer
335       */
336 <    public final CountedCompleter getCompleter() {
336 >    public final CountedCompleter<?> getCompleter() {
337          return completer;
338      }
339  
# Line 373 | Line 384 | public abstract class CountedCompleter e
384       * else marks this task as complete.
385       */
386      public final void tryComplete() {
387 <        CountedCompleter a = this, s = a;
387 >        CountedCompleter<?> a = this, s = a;
388          for (int c;;) {
389              if ((c = a.pending) == 0) {
390                  a.onCompletion(s);
# Line 389 | Line 400 | public abstract class CountedCompleter e
400  
401      /**
402       * Regardless of pending count, invokes {@link #onCompletion},
403 <     * marks this task as complete with a {@code null} return value,
404 <     * and further triggers {@link #tryComplete} on this task's
405 <     * completer, if one exists. This method may be useful when
406 <     * forcing completion as soon as any one (versus all) of several
407 <     * subtask results are obtained.
403 >     * marks this task as complete and further triggers {@link
404 >     * #tryComplete} on this task's completer, if one exists. This
405 >     * method may be useful when forcing completion as soon as any one
406 >     * (versus all) of several subtask results are obtained.  The
407 >     * given rawResult is used as an argument to {@link #setRawResult}
408 >     * before marking this task as complete; its value is meaningful
409 >     * only for classes overriding {@code setRawResult}.
410       *
411 <     * @param mustBeNull the {@code null} completion value
411 >     * @param rawResult the raw result
412       */
413 <    public void complete(Void mustBeNull) {
414 <        CountedCompleter p;
413 >    public void complete(T rawResult) {
414 >        CountedCompleter<?> p;
415          onCompletion(this);
416 +        setRawResult(rawResult);
417          quietlyComplete();
418          if ((p = completer) != null)
419              p.tryComplete();
# Line 409 | Line 423 | public abstract class CountedCompleter e
423       * Support for FJT exception propagation
424       */
425      void internalPropagateException(Throwable ex) {
426 <        CountedCompleter a = this, s = a;
426 >        CountedCompleter<?> a = this, s = a;
427          while (a.onExceptionalCompletion(ex, s) &&
428                 (a = (s = a).completer) != null && a.status >= 0)
429              a.recordExceptionalCompletion(ex);
# Line 424 | Line 438 | public abstract class CountedCompleter e
438      }
439  
440      /**
441 <     * Always returns {@code null}.
441 >     * Returns the result of the computation. By default
442 >     * returns {@code null}, which is appropriate for {@code Void}
443 >     * actions, but in other cases should be overridden.
444       *
445 <     * @return {@code null} always
445 >     * @return the result of the computation
446       */
447 <    public final Void getRawResult() { return null; }
447 >    public T getRawResult() { return null; }
448  
449      /**
450 <     * Requires null completion value.
450 >     * A method that result-bearing CountedCompleters may optionally
451 >     * use to help maintain result data.  By default, does nothing.
452       */
453 <    protected final void setRawResult(Void mustBeNull) { }
453 >    protected void setRawResult(T t) { }
454  
455      // Unsafe mechanics
456      private static final sun.misc.Unsafe U;

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines