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.1 by dl, Mon Apr 9 13:12:18 2012 UTC vs.
Revision 1.3 by dl, Thu Aug 16 12:25:03 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 21 | Line 21 | package jsr166y;
21   * #tryComplete}, if the pending action count is nonzero, it is
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 most basic synchronization
25 < * constructs, these methods affect only internal counts; they do not
26 < * establish any further internal bookkeeping. In particular, the
27 < * identities of pending tasks are not maintained. As illustrated
28 < * below, you can create subclasses that do record some or all pended
29 < * tasks or their results when needed.
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.
31   *
32   * <p>A concrete CountedCompleter class must define method {@link
33   * #compute}, that should, in almost all use cases, invoke {@code
34 < * tryComplete()} before returning. The class may also optionally
34 > * tryComplete()} once before returning. The class may also optionally
35   * override method {@link #onCompletion} to perform an action upon
36 < * normal completion.
36 > * normal completion, and method {@link #onExceptionalCompletion} to
37 > * perform an action upon any exception.
38 > *
39 > * <p>CountedCompleters most often do not bear results, in which case
40 > * they are normally declared as {@code CountedCompleter<Void>}, and
41 > * will always return {@code null} as a result value.  In other cases,
42 > * you should override method {@link #getRawResult} to provide a
43 > * result from {@code join(), invoke()}, and related methods. (Method
44 > * {@link #setRawResult} by default plays no role in CountedCompleters
45 > * but may be overridden for example to maintain fields holding result
46 > * data.)
47   *
48   * <p>A CountedCompleter that does not itself have a completer (i.e.,
49   * one for which {@link #getCompleter} returns {@code null}) can be
# Line 44 | Line 55 | package jsr166y;
55   * {@link #complete}, {@link ForkJoinTask#cancel}, {@link
56   * ForkJoinTask#completeExceptionally} or upon exceptional completion
57   * of method {@code compute}. Upon any exceptional completion, the
58 < * exception is relayed to a task's completer (and its completer, and
59 < * so on), if one exists and it has not otherwise already completed.
58 > * exception may be relayed to a task's completer (and its completer,
59 > * and so on), if one exists and it has not otherwise already
60 > * completed.
61   *
62   * <p><b>Sample Usages.</b>
63   *
64   * <p><b>Parallel recursive decomposition.</b> CountedCompleters may
65   * be arranged in trees similar to those often used with {@link
66   * RecursiveAction}s, although the constructions involved in setting
67 < * them up typically vary. Even though they entail a bit more
67 > * them up typically vary. Here, the completer of each task is its
68 > * parent in the computation tree. Even though they entail a bit more
69   * bookkeeping, CountedCompleters may be better choices when applying
70   * a possibly time-consuming operation (that cannot be further
71   * subdivided) to each element of an array or collection; especially
# Line 77 | Line 90 | package jsr166y;
90   * <pre> {@code
91   * class MyOperation<E> { void apply(E e) { ... }  }
92   *
93 < * class ForEach<E> extends CountedCompleter {
93 > * class ForEach<E> extends CountedCompleter<Void> {
94   *
95   *     public static <E> void forEach(ForkJoinPool pool, E[] array, MyOperation<E> op) {
96   *         pool.invoke(new ForEach<E>(null, array, op, 0, array.length));
97   *     }
98   *
99   *     final E[] array; final MyOperation<E> op; final int lo, hi;
100 < *     ForEach(CountedCompleter p, E[] array, MyOperation<E> op, int lo, int hi) {
100 > *     ForEach(CountedCompleter<?> p, E[] array, MyOperation<E> op, int lo, int hi) {
101   *         super(p);
102   *         this.array = array; this.op = op; this.lo = lo; this.hi = hi;
103   *     }
# Line 159 | Line 172 | package jsr166y;
172   * and reductions are all of type {@code E}), one way to do this in
173   * divide and conquer designs is to have each subtask record its
174   * sibling, so that it can be accessed in method {@code onCompletion}.
175 < * For clarity, this class uses explicit left and right subtasks, but
176 < * variants of other streamlinings seen in the above example may also
177 < * apply.
175 > * This technique applies to reductions in which the order of
176 > * combining left and right results does not matter; ordered
177 > * reductions require explicit left/right designations.  Variants of
178 > * other streamlinings seen in the above examples may also apply.
179   *
180   * <pre> {@code
181   * class MyMapper<E> { E apply(E v) {  ...  } }
182   * class MyReducer<E> { E apply(E x, E y) {  ...  } }
183 < * class MapReducer<E> extends CountedCompleter {
183 > * class MapReducer<E> extends CountedCompleter<E> {
184   *     final E[] array; final MyMapper<E> mapper;
185   *     final MyReducer<E> reducer; final int lo, hi;
186 < *     MapReducer sibling;
186 > *     MapReducer<E> sibling;
187   *     E result;
188   *     MapReducer(CountedCompleter p, E[] array, MyMapper<E> mapper,
189   *                MyReducer<E> reducer, int lo, int hi) {
# Line 204 | Line 218 | package jsr166y;
218   *                result = reducer.apply(child.result, sib.result);
219   *         }
220   *     }
221 + *     public E getRawResult() { return result; }
222   *
223   *     public static <E> E mapReduce(ForkJoinPool pool, E[] array,
224   *                                   MyMapper<E> mapper, MyReducer<E> reducer) {
225 < *         MapReducer<E> mr = new MapReducer<E>(null, array, mapper,
226 < *                                              reducer, 0, array.length);
212 < *         pool.invoke(mr);
213 < *         return mr.result;
225 > *         return pool.invoke(new MapReducer<E>(null, array, mapper,
226 > *                                              reducer, 0, array.length));
227   *     }
228   * } }</pre>
229   *
# Line 220 | Line 233 | package jsr166y;
233   * triggers another async task. For example:
234   *
235   * <pre> {@code
236 < * class HeaderBuilder extends CountedCompleter { ... }
237 < * class BodyBuilder extends CountedCompleter { ... }
238 < * class PacketSender extends CountedCompleter {
236 > * class HeaderBuilder extends CountedCompleter<...> { ... }
237 > * class BodyBuilder extends CountedCompleter<...> { ... }
238 > * class PacketSender extends CountedCompleter<...> {
239   *     PacketSender(...) { super(null, 1); ... } // trigger on second completion
240   *     public void compute() { } // never called
241 < *     public void onCompletion(CountedCompleter caller) { sendPacket(); }
241 > *     public void onCompletion(CountedCompleter<?> caller) { sendPacket(); }
242   * }
243   * // sample use:
244   * PacketSender p = new PacketSender();
# Line 236 | Line 249 | package jsr166y;
249   * @since 1.8
250   * @author Doug Lea
251   */
252 < public abstract class CountedCompleter extends ForkJoinTask<Void> {
252 > public abstract class CountedCompleter<T> extends ForkJoinTask<T> {
253 >    private static final long serialVersionUID = 5232453752276485070L;
254 >
255      /** This task's completer, or null if none */
256 <    final CountedCompleter completer;
256 >    final CountedCompleter<?> completer;
257      /** The number of pending tasks until completion */
258      volatile int pending;
259  
# Line 249 | Line 264 | public abstract class CountedCompleter e
264       * @param completer this tasks completer, or {@code null} if none
265       * @param initialPendingCount the initial pending count
266       */
267 <    protected CountedCompleter(CountedCompleter completer,
267 >    protected CountedCompleter(CountedCompleter<?> completer,
268                                 int initialPendingCount) {
269          this.completer = completer;
270          this.pending = initialPendingCount;
# Line 261 | Line 276 | public abstract class CountedCompleter e
276       *
277       * @param completer this tasks completer, or {@code null} if none
278       */
279 <    protected CountedCompleter(CountedCompleter completer) {
279 >    protected CountedCompleter(CountedCompleter<?> completer) {
280          this.completer = completer;
281      }
282  
# Line 279 | Line 294 | public abstract class CountedCompleter e
294      public abstract void compute();
295  
296      /**
297 <     * Executes the completion action when method {@link #tryComplete}
298 <     * is invoked and there are no pending counts, or when the
299 <     * unconditional method {@link #complete} is invoked.  By default,
300 <     * this method does nothing.
297 >     * Performs an action when method {@link #tryComplete} is invoked
298 >     * and there are no pending counts, or when the unconditional
299 >     * method {@link #complete} is invoked.  By default, this method
300 >     * does nothing.
301 >     *
302 >     * @param caller the task invoking this method (which may
303 >     * be this task itself).
304 >     */
305 >    public void onCompletion(CountedCompleter<?> caller) {
306 >    }
307 >
308 >    /**
309 >     * Performs an action when method {@link #completeExceptionally}
310 >     * is invoked or method {@link #compute} throws an exception, and
311 >     * this task has not otherwise already completed normally. On
312 >     * entry to this method, this task {@link
313 >     * ForkJoinTask#isCompletedAbnormally}.  The return value of this
314 >     * method controls further propagation: If {@code true} and this
315 >     * task has a completer, then this completer is also completed
316 >     * exceptionally.  The default implementation of this method does
317 >     * nothing except return {@code true}.
318       *
319 +     * @param ex the exception
320       * @param caller the task invoking this method (which may
321       * be this task itself).
322 +     * @return true if this exception should be propagated to this
323 +     * tasks completer, if one exists.
324       */
325 <    public void onCompletion(CountedCompleter caller) {
325 >    public boolean onExceptionalCompletion(Throwable ex, CountedCompleter<?> caller) {
326 >        return true;
327      }
328  
329      /**
# Line 296 | Line 332 | public abstract class CountedCompleter e
332       *
333       * @return the completer
334       */
335 <    public final CountedCompleter getCompleter() {
335 >    public final CountedCompleter<?> getCompleter() {
336          return completer;
337      }
338  
# Line 347 | Line 383 | public abstract class CountedCompleter e
383       * else marks this task as complete.
384       */
385      public final void tryComplete() {
386 <        for (CountedCompleter a = this, s = a;;) {
387 <            int c;
386 >        CountedCompleter<?> a = this, s = a;
387 >        for (int c;;) {
388              if ((c = a.pending) == 0) {
389                  a.onCompletion(s);
390                  if ((a = (s = a).completer) == null) {
# Line 363 | Line 399 | public abstract class CountedCompleter e
399  
400      /**
401       * Regardless of pending count, invokes {@link #onCompletion},
402 <     * marks this task as complete with a {@code null} return value,
403 <     * and further triggers {@link #tryComplete} on this task's
404 <     * completer, if one exists. This method may be useful when
405 <     * forcing completion as soon as any one (versus all) of several
406 <     * subtask results are obtained.
402 >     * marks this task as complete and further triggers {@link
403 >     * #tryComplete} on this task's completer, if one exists. This
404 >     * method may be useful when forcing completion as soon as any one
405 >     * (versus all) of several subtask results are obtained.  The
406 >     * given rawResult is used as an argument to {@link #setRawResult}
407 >     * before marking this task as complete; its value is meaningful
408 >     * only for classes overriding {@code setRawResult}.
409       *
410 <     * @param mustBeNull the {@code null} completion value
410 >     * @param rawResult the raw result
411       */
412 <    public void complete(Void mustBeNull) {
413 <        CountedCompleter p;
412 >    public void complete(T rawResult) {
413 >        CountedCompleter<?> p;
414          onCompletion(this);
415 +        setRawResult(rawResult);
416          quietlyComplete();
417          if ((p = completer) != null)
418              p.tryComplete();
419      }
420  
421      /**
422 +     * Support for FJT exception propagation
423 +     */
424 +    void internalPropagateException(Throwable ex) {
425 +        CountedCompleter<?> a = this, s = a;
426 +        while (a.onExceptionalCompletion(ex, s) &&
427 +               (a = (s = a).completer) != null && a.status >= 0)
428 +            a.recordExceptionalCompletion(ex);
429 +    }
430 +
431 +    /**
432       * Implements execution conventions for CountedCompleters
433       */
434      protected final boolean exec() {
# Line 388 | Line 437 | public abstract class CountedCompleter e
437      }
438  
439      /**
440 <     * Always returns {@code null}.
440 >     * Returns the result of the computation. By default
441 >     * returns {@code null}, which is appropriate for {@code Void}
442 >     * actions, but in other cases should be overridden.
443       *
444 <     * @return {@code null} always
444 >     * @return the result of the computation
445       */
446 <    public final Void getRawResult() { return null; }
446 >    public T getRawResult() { return null; }
447  
448      /**
449 <     * Requires null completion value.
450 <     */
400 <    protected final void setRawResult(Void mustBeNull) { }
401 <
402 <    /**
403 <     * Support for FJT exception propagation
449 >     * A method that result-bearing CountedCompleters may optionally
450 >     * use to help maintain result data.  By default, does nothing.
451       */
452 <    final ForkJoinTask<?> internalGetCompleter() { return completer; }
452 >    protected void setRawResult(T t) { }
453  
454      // Unsafe mechanics
455      private static final sun.misc.Unsafe U;

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines