--- jsr166/src/jsr166y/CountedCompleter.java 2012/04/09 13:12:18 1.1
+++ jsr166/src/jsr166y/CountedCompleter.java 2012/04/21 11:45:20 1.2
@@ -21,18 +21,20 @@ package jsr166y;
* #tryComplete}, if the pending action count is nonzero, it is
* decremented; otherwise, the completion action is performed, and if
* this completer itself has a completer, the process is continued
- * with its completer. As is the case with most basic synchronization
- * constructs, these methods affect only internal counts; they do not
- * establish any further internal bookkeeping. In particular, the
- * identities of pending tasks are not maintained. As illustrated
- * below, you can create subclasses that do record some or all pended
- * tasks or their results when needed.
+ * with its completer. As is the case with related synchronization
+ * components such as {@link Phaser} and {@link
+ * java.util.concurrent.Semaphore} these methods affect only internal
+ * counts; they do not establish any further internal bookkeeping. In
+ * particular, the identities of pending tasks are not maintained. As
+ * illustrated below, you can create subclasses that do record some or
+ * all pended tasks or their results when needed.
*
*
A concrete CountedCompleter class must define method {@link
* #compute}, that should, in almost all use cases, invoke {@code
- * tryComplete()} before returning. The class may also optionally
+ * tryComplete()} once before returning. The class may also optionally
* override method {@link #onCompletion} to perform an action upon
- * normal completion.
+ * normal completion, and method {@link #onExceptionalCompletion} to
+ * perform an action upon any exception.
*
*
A CountedCompleter that does not itself have a completer (i.e.,
* one for which {@link #getCompleter} returns {@code null}) can be
@@ -44,8 +46,9 @@ package jsr166y;
* {@link #complete}, {@link ForkJoinTask#cancel}, {@link
* ForkJoinTask#completeExceptionally} or upon exceptional completion
* of method {@code compute}. Upon any exceptional completion, the
- * exception is relayed to a task's completer (and its completer, and
- * so on), if one exists and it has not otherwise already completed.
+ * exception may be relayed to a task's completer (and its completer,
+ * and so on), if one exists and it has not otherwise already
+ * completed.
*
*
Sample Usages.
*
@@ -237,6 +240,8 @@ package jsr166y;
* @author Doug Lea
*/
public abstract class CountedCompleter extends ForkJoinTask {
+ private static final long serialVersionUID = 5232453752276485070L;
+
/** This task's completer, or null if none */
final CountedCompleter completer;
/** The number of pending tasks until completion */
@@ -279,10 +284,10 @@ public abstract class CountedCompleter e
public abstract void compute();
/**
- * Executes the completion action when method {@link #tryComplete}
- * is invoked and there are no pending counts, or when the
- * unconditional method {@link #complete} is invoked. By default,
- * this method does nothing.
+ * Performs an action when method {@link #tryComplete} is invoked
+ * and there are no pending counts, or when the unconditional
+ * method {@link #complete} is invoked. By default, this method
+ * does nothing.
*
* @param caller the task invoking this method (which may
* be this task itself).
@@ -291,6 +296,27 @@ public abstract class CountedCompleter e
}
/**
+ * Performs an action when method {@link #completeExceptionally}
+ * is invoked or method {@link #compute} throws an exception, and
+ * this task has not otherwise already completed normally. On
+ * entry to this method, this task {@link
+ * ForkJoinTask#isCompletedAbnormally}. The return value of this
+ * method controls further propagation: If {@code true} and this
+ * task has a completer, then this completer is also completed
+ * exceptionally. The default implementation of this method does
+ * nothing except return {@code true}.
+ *
+ * @param ex the exception
+ * @param caller the task invoking this method (which may
+ * be this task itself).
+ * @return true if this exception should be propagated to this
+ * tasks completer, if one exists.
+ */
+ public boolean onExceptionalCompletion(Throwable ex, CountedCompleter caller) {
+ return true;
+ }
+
+ /**
* Returns the completer established in this task's constructor,
* or {@code null} if none.
*
@@ -347,8 +373,8 @@ public abstract class CountedCompleter e
* else marks this task as complete.
*/
public final void tryComplete() {
- for (CountedCompleter a = this, s = a;;) {
- int c;
+ CountedCompleter a = this, s = a;
+ for (int c;;) {
if ((c = a.pending) == 0) {
a.onCompletion(s);
if ((a = (s = a).completer) == null) {
@@ -380,6 +406,16 @@ public abstract class CountedCompleter e
}
/**
+ * Support for FJT exception propagation
+ */
+ void internalPropagateException(Throwable ex) {
+ CountedCompleter a = this, s = a;
+ while (a.onExceptionalCompletion(ex, s) &&
+ (a = (s = a).completer) != null && a.status >= 0)
+ a.recordExceptionalCompletion(ex);
+ }
+
+ /**
* Implements execution conventions for CountedCompleters
*/
protected final boolean exec() {
@@ -399,11 +435,6 @@ public abstract class CountedCompleter e
*/
protected final void setRawResult(Void mustBeNull) { }
- /**
- * Support for FJT exception propagation
- */
- final ForkJoinTask> internalGetCompleter() { return completer; }
-
// Unsafe mechanics
private static final sun.misc.Unsafe U;
private static final long PENDING;