--- jsr166/src/jsr166y/ForkJoinTask.java 2009/08/02 22:58:50 1.31
+++ jsr166/src/jsr166y/ForkJoinTask.java 2009/08/06 23:08:50 1.42
@@ -12,6 +12,7 @@ import java.io.Serializable;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
+import java.util.RandomAccess;
import java.util.Map;
import java.util.WeakHashMap;
@@ -54,7 +55,7 @@ import java.util.WeakHashMap;
* restriction is in part enforced by not permitting checked
* exceptions such as {@code IOExceptions} to be thrown. However,
* computations may still encounter unchecked exceptions, that are
- * rethrown to callers attempting join them. These exceptions may
+ * rethrown to callers attempting to join them. These exceptions may
* additionally include RejectedExecutionExceptions stemming from
* internal resource exhaustion such as failure to allocate internal
* task queues.
@@ -67,15 +68,27 @@ import java.util.WeakHashMap;
* execute other tasks while awaiting joins, which is sometimes more
* efficient but only applies when all subtasks are known to be
* strictly tree-structured. Method {@link #invoke} is semantically
- * equivalent to {@code fork(); join()} but always attempts to
- * begin execution in the current thread. The "quiet" forms
- * of these methods do not extract results or report exceptions. These
+ * equivalent to {@code fork(); join()} but always attempts to begin
+ * execution in the current thread. The "quiet" forms of
+ * these methods do not extract results or report exceptions. These
* may be useful when a set of tasks are being executed, and you need
* to delay processing of results or exceptions until all complete.
* Method {@code invokeAll} (available in multiple versions)
* performs the most common form of parallel invocation: forking a set
* of tasks and joining them all.
*
+ *
The execution status of tasks may be queried at several levels
+ * of detail: {@link #isDone} is true if a task completed in any way
+ * (including the case where a task was cancelled without executing);
+ * {@link #isCompletedNormally} is true if a task completed without
+ * cancellation or encountering an exception; {@link #isCancelled} is
+ * true if the task was cancelled (in which case {@link #getException}
+ * returns a {@link java.util.concurrent.CancellationException}); and
+ * {@link #isCompletedAbnormally} is true if a task was either
+ * cancelled or encountered an exception, in which case {@link
+ * #getException} will return either the encountered exception or
+ * {@link java.util.concurrent.CancellationException}.
+ *
*
The ForkJoinTask class is not usually directly subclassed.
* Instead, you subclass one of the abstract classes that support a
* particular style of fork/join processing, typically {@link
@@ -85,42 +98,41 @@ import java.util.WeakHashMap;
* established in a constructor, and then defines a {@code compute}
* method that somehow uses the control methods supplied by this base
* class. While these methods have {@code public} access (to allow
- * instances of different task subclasses to call each others
+ * instances of different task subclasses to call each other's
* methods), some of them may only be called from within other
* ForkJoinTasks (as may be determined using method {@link
* #inForkJoinPool}). Attempts to invoke them in other contexts
* result in exceptions or errors, possibly including
* ClassCastException.
*
- *
Most base support methods are {@code final} because their
- * implementations are intrinsically tied to the underlying
- * lightweight task scheduling framework, and so cannot be overridden.
- * Developers creating new basic styles of fork/join processing should
- * minimally implement {@code protected} methods
- * {@link #exec}, {@link #setRawResult}, and
- * {@link #getRawResult}, while also introducing an abstract
- * computational method that can be implemented in its subclasses,
- * possibly relying on other {@code protected} methods provided
- * by this class.
+ *
Most base support methods are {@code final}, to prevent
+ * overriding of implementations that are intrinsically tied to the
+ * underlying lightweight task scheduling framework. Developers
+ * creating new basic styles of fork/join processing should minimally
+ * implement {@code protected} methods {@link #exec}, {@link
+ * #setRawResult}, and {@link #getRawResult}, while also introducing
+ * an abstract computational method that can be implemented in its
+ * subclasses, possibly relying on other {@code protected} methods
+ * provided by this class.
*
*
ForkJoinTasks should perform relatively small amounts of
- * computations, otherwise splitting into smaller tasks. As a very
- * rough rule of thumb, a task should perform more than 100 and less
- * than 10000 basic computational steps. If tasks are too big, then
- * parallelism cannot improve throughput. If too small, then memory
- * and internal task maintenance overhead may overwhelm processing.
+ * computation. Large tasks should be split into smaller subtasks,
+ * usually via recursive decomposition. As a very rough rule of thumb,
+ * a task should perform more than 100 and less than 10000 basic
+ * computational steps. If tasks are too big, then parallelism cannot
+ * improve throughput. If too small, then memory and internal task
+ * maintenance overhead may overwhelm processing.
*
- *
This class provides {@code adapt} methods for {@link
- * java.lang.Runnable} and {@link java.util.concurrent.Callable}, that
- * may be of use when mixing execution of ForkJoinTasks with other
- * kinds of tasks. When all tasks are of this form, consider using a
- * pool in {@link ForkJoinPool#setAsyncMode}.
+ *
This class provides {@code adapt} methods for {@link Runnable}
+ * and {@link Callable}, that may be of use when mixing execution of
+ * {@code ForkJoinTasks} with other kinds of tasks. When all tasks
+ * are of this form, consider using a pool in
+ * {@linkplain ForkJoinPool#setAsyncMode async mode}.
*
- *
ForkJoinTasks are {@code Serializable}, which enables them
- * to be used in extensions such as remote execution frameworks. It is
- * in general sensible to serialize tasks only before or after, but
- * not during execution. Serialization is not relied on during
- * execution itself.
+ *
ForkJoinTasks are {@code Serializable}, which enables them to be
+ * used in extensions such as remote execution frameworks. It is
+ * sensible to serialize tasks only before or after, but not during,
+ * execution. Serialization is not relied on during execution itself.
*
* @since 1.7
* @author Doug Lea
@@ -378,10 +390,13 @@ public abstract class ForkJoinTask im
/**
* Returns result or throws exception using j.u.c.Future conventions.
- * Only call when {@code isDone} known to be true.
+ * Only call when {@code isDone} known to be true or thread known
+ * to be interrupted.
*/
private V reportFutureResult()
- throws ExecutionException, InterruptedException {
+ throws InterruptedException, ExecutionException {
+ if (Thread.interrupted())
+ throw new InterruptedException();
int s = status & COMPLETION_MASK;
if (s < NORMAL) {
Throwable ex;
@@ -389,8 +404,6 @@ public abstract class ForkJoinTask im
throw new CancellationException();
if (s == EXCEPTIONAL && (ex = exceptionMap.get(this)) != null)
throw new ExecutionException(ex);
- if (Thread.interrupted())
- throw new InterruptedException();
}
return getRawResult();
}
@@ -401,17 +414,18 @@ public abstract class ForkJoinTask im
*/
private V reportTimedFutureResult()
throws InterruptedException, ExecutionException, TimeoutException {
+ if (Thread.interrupted())
+ throw new InterruptedException();
Throwable ex;
int s = status & COMPLETION_MASK;
if (s == NORMAL)
return getRawResult();
- if (s == CANCELLED)
+ else if (s == CANCELLED)
throw new CancellationException();
- if (s == EXCEPTIONAL && (ex = exceptionMap.get(this)) != null)
+ else if (s == EXCEPTIONAL && (ex = exceptionMap.get(this)) != null)
throw new ExecutionException(ex);
- if (Thread.interrupted())
- throw new InterruptedException();
- throw new TimeoutException();
+ else
+ throw new TimeoutException();
}
// internal execution methods
@@ -513,7 +527,7 @@ public abstract class ForkJoinTask im
}
/**
- * Returns the result of the computation when it is ready.
+ * Returns the result of the computation when it {@link #isDone is done}.
* This method differs from {@link #get()} in that
* abnormal completion results in {@code RuntimeException} or
* {@code Error}, not {@code ExecutionException}.
@@ -529,10 +543,9 @@ public abstract class ForkJoinTask im
/**
* Commences performing this task, awaits its completion if
- * necessary, and return its result.
+ * necessary, and return its result, or throws an (unchecked)
+ * exception if the underlying computation did so.
*
- * @throws Throwable (a RuntimeException, Error, or unchecked
- * exception) if the underlying computation did so
* @return the computed result
*/
public final V invoke() {
@@ -543,8 +556,13 @@ public abstract class ForkJoinTask im
}
/**
- * Forks the given tasks, returning when {@code isDone} holds
- * for each task or an exception is encountered.
+ * Forks the given tasks, returning when {@code isDone} holds for
+ * each task or an (unchecked) exception is encountered, in which
+ * case the exception is rethrown. If either task encounters an
+ * exception, the other one may be, but is not guaranteed to be,
+ * cancelled. If both tasks throw an exception, then this method
+ * throws one of them. The individual status of each task may be
+ * checked using {@link #getException()} and related methods.
*
* This method may be invoked only from within {@code
* ForkJoinTask} computations (as may be determined using method
@@ -555,7 +573,6 @@ public abstract class ForkJoinTask im
* @param t1 the first task
* @param t2 the second task
* @throws NullPointerException if any task is null
- * @throws RuntimeException or Error if a task did so
*/
public static void invokeAll(ForkJoinTask> t1, ForkJoinTask> t2) {
t2.fork();
@@ -565,9 +582,13 @@ public abstract class ForkJoinTask im
/**
* Forks the given tasks, returning when {@code isDone} holds for
- * each task or an exception is encountered. If any task
- * encounters an exception, others may be, but are not guaranteed
- * to be, cancelled.
+ * each task or an (unchecked) exception is encountered, in which
+ * case the exception is rethrown. If any task encounters an
+ * exception, others may be, but are not guaranteed to be,
+ * cancelled. If more than one task encounters an exception, then
+ * this method throws any one of these exceptions. The individual
+ * status of each task may be checked using {@link #getException()}
+ * and related methods.
*
* This method may be invoked only from within {@code
* ForkJoinTask} computations (as may be determined using method
@@ -575,12 +596,8 @@ public abstract class ForkJoinTask im
* result in exceptions or errors, possibly including {@code
* ClassCastException}.
*
- * Overloadings of this method exist for the special cases
- * of one to four arguments.
- *
* @param tasks the tasks
- * @throws NullPointerException if tasks or any element are null
- * @throws RuntimeException or Error if any task did so
+ * @throws NullPointerException if any task is null
*/
public static void invokeAll(ForkJoinTask>... tasks) {
Throwable ex = null;
@@ -616,10 +633,16 @@ public abstract class ForkJoinTask im
}
/**
- * Forks all tasks in the collection, returning when {@code
- * isDone} holds for each task or an exception is encountered.
- * If any task encounters an exception, others may be, but are
- * not guaranteed to be, cancelled.
+ * Forks all tasks in the specified collection, returning when
+ * {@code isDone} holds for each task or an (unchecked) exception
+ * is encountered. If any task encounters an exception, others
+ * may be, but are not guaranteed to be, cancelled. If more than
+ * one task encounters an exception, then this method throws any
+ * one of these exceptions. The individual status of each task
+ * may be checked using {@link #getException()} and related
+ * methods. The behavior of this operation is undefined if the
+ * specified collection is modified while the operation is in
+ * progress.
*
* This method may be invoked only from within {@code
* ForkJoinTask} computations (as may be determined using method
@@ -630,10 +653,9 @@ public abstract class ForkJoinTask im
* @param tasks the collection of tasks
* @return the tasks argument, to simplify usage
* @throws NullPointerException if tasks or any element are null
- * @throws RuntimeException or Error if any task did so
*/
public static > Collection invokeAll(Collection tasks) {
- if (!(tasks instanceof List>)) {
+ if (!(tasks instanceof RandomAccess) || !(tasks instanceof List>)) {
invokeAll(tasks.toArray(new ForkJoinTask>[tasks.size()]));
return tasks;
}
@@ -674,35 +696,13 @@ public abstract class ForkJoinTask im
}
/**
- * Returns {@code true} if the computation performed by this task
- * has completed (or has been cancelled).
- *
- * @return {@code true} if this computation has completed
- */
- public final boolean isDone() {
- return status < 0;
- }
-
- /**
- * Returns {@code true} if this task was cancelled.
- *
- * @return {@code true} if this task was cancelled
- */
- public final boolean isCancelled() {
- return (status & COMPLETION_MASK) == CANCELLED;
- }
-
- /**
- * Asserts that the results of this task's computation will not be
- * used. If a cancellation occurs before attempting to execute this
- * task, execution will be suppressed, {@link #isCancelled}
- * will report true, and {@link #join} will result in a
- * {@code CancellationException} being thrown. Otherwise, when
- * cancellation races with completion, there are no guarantees
- * about whether {@code isCancelled} will report {@code true},
- * whether {@code join} will return normally or via an exception,
- * or whether these behaviors will remain consistent upon repeated
- * invocation.
+ * Attempts to cancel execution of this task. This attempt will
+ * fail if the task has already completed, has already been
+ * cancelled, or could not be cancelled for some other reason. If
+ * successful, and this task has not started when cancel is
+ * called, execution of this task is suppressed, {@link
+ * #isCancelled} will report true, and {@link #join} will result
+ * in a {@code CancellationException} being thrown.
*
* This method may be overridden in subclasses, but if so, must
* still ensure that these minimal properties hold. In particular,
@@ -714,7 +714,7 @@ public abstract class ForkJoinTask im
* invoke {@link #completeExceptionally}.
*
* @param mayInterruptIfRunning this value is ignored in the
- * default implementation because tasks are not in general
+ * default implementation because tasks are not
* cancelled via interruption
*
* @return {@code true} if this task is now cancelled
@@ -724,6 +724,14 @@ public abstract class ForkJoinTask im
return (status & COMPLETION_MASK) == CANCELLED;
}
+ public final boolean isDone() {
+ return status < 0;
+ }
+
+ public final boolean isCancelled() {
+ return (status & COMPLETION_MASK) == CANCELLED;
+ }
+
/**
* Returns {@code true} if this task threw an exception or was cancelled.
*
@@ -734,6 +742,17 @@ public abstract class ForkJoinTask im
}
/**
+ * Returns {@code true} if this task completed without throwing an
+ * exception and was not cancelled.
+ *
+ * @return {@code true} if this task completed without throwing an
+ * exception and was not cancelled
+ */
+ public final boolean isCompletedNormally() {
+ return (status & COMPLETION_MASK) == NORMAL;
+ }
+
+ /**
* Returns the exception thrown by the base computation, or a
* {@code CancellationException} if cancelled, or {@code null} if
* none or if the method has not yet completed.
@@ -742,11 +761,9 @@ public abstract class ForkJoinTask im
*/
public final Throwable getException() {
int s = status & COMPLETION_MASK;
- if (s >= NORMAL)
- return null;
- if (s == CANCELLED)
- return new CancellationException();
- return exceptionMap.get(this);
+ return ((s >= NORMAL) ? null :
+ (s == CANCELLED) ? new CancellationException() :
+ exceptionMap.get(this));
}
/**
@@ -808,13 +825,13 @@ public abstract class ForkJoinTask im
}
/**
- * Possibly executes other tasks until this task is ready, then
- * returns the result of the computation. This method may be more
- * efficient than {@code join}, but is only applicable when
- * there are no potential dependencies between continuation of the
- * current task and that of any other task that might be executed
- * while helping. (This usually holds for pure divide-and-conquer
- * tasks).
+ * Possibly executes other tasks until this task {@link #isDone is
+ * done}, then returns the result of the computation. This method
+ * may be more efficient than {@code join}, but is only applicable
+ * when there are no potential dependencies between continuation
+ * of the current task and that of any other task that might be
+ * executed while helping. (This usually holds for pure
+ * divide-and-conquer tasks).
*
* This method may be invoked only from within {@code
* ForkJoinTask} computations (as may be determined using method
@@ -832,7 +849,10 @@ public abstract class ForkJoinTask im
}
/**
- * Possibly executes other tasks until this task is ready.
+ * Possibly executes other tasks until this task {@link #isDone is
+ * done}. This method may be useful when processing collections
+ * of tasks when some have been cancelled or otherwise known to
+ * have aborted.
*
* This method may be invoked only from within {@code
* ForkJoinTask} computations (as may be determined using method
@@ -877,9 +897,10 @@ public abstract class ForkJoinTask im
/**
* Possibly executes tasks until the pool hosting the current task
- * {@link ForkJoinPool#isQuiescent}. This method may be of use in
- * designs in which many tasks are forked, but none are explicitly
- * joined, instead executing them until all are processed.
+ * {@link ForkJoinPool#isQuiescent is quiescent}. This method may
+ * be of use in designs in which many tasks are forked, but none
+ * are explicitly joined, instead executing them until all are
+ * processed.
*
* This method may be invoked only from within {@code
* ForkJoinTask} computations (as may be determined using method
@@ -1023,11 +1044,10 @@ public abstract class ForkJoinTask im
* called otherwise. The return value controls whether this task
* is considered to be done normally. It may return false in
* asynchronous actions that require explicit invocations of
- * {@link #complete} to become joinable. It may throw exceptions
- * to indicate abnormal exit.
+ * {@link #complete} to become joinable. It may also throw an
+ * (unchecked) exception to indicate abnormal exit.
*
* @return {@code true} if completed normally
- * @throws Error or RuntimeException if encountered during computation
*/
protected abstract boolean exec();