--- jsr166/src/jsr166y/ForkJoinTask.java 2009/01/06 14:30:31 1.1 +++ jsr166/src/jsr166y/ForkJoinTask.java 2009/01/07 16:07:37 1.2 @@ -13,24 +13,32 @@ import sun.misc.Unsafe; import java.lang.reflect.*; /** - * Abstract base class for tasks that run within a ForkJoinPool. A - * ForkJoinTask is a thread-like entity that is much lighter weight - * than a normal thread. Huge numbers of tasks and subtasks may be - * hosted by a small number of actual threads in a ForkJoinPool, - * at the price of some usage limitations. - * - *
ForkJoinTasks are forms of Futures supporting a - * limited range of use. The "lightness" of ForkJoinTasks is due to a - * set of restrictions (that are only partially statically - * enforceable) reflecting their intended use as computational tasks - * calculating pure functions or operating on purely isolated objects. - * The primary coordination mechanisms supported for ForkJoinTasks are - * fork, that arranges asynchronous execution, and - * join, that doesn't proceed until the task's result has - * been computed. (Cancellation is also supported). The computation - * defined in the compute method should avoid - * synchronized methods or blocks, and should minimize - * blocking synchronization apart from joining other tasks or using + * Abstract base class for tasks that run within a {@link + * ForkJoinPool}. A ForkJoinTask is a thread-like entity that is much + * lighter weight than a normal thread. Huge numbers of tasks and + * subtasks may be hosted by a small number of actual threads in a + * ForkJoinPool, at the price of some usage limitations. + * + *
A "main" ForkJoinTask begins execution when submitted to a
+ * {@link ForkJoinPool}. Once started, it will usually in turn start
+ * other subtasks. As indicated by the name of this class, many
+ * programs using ForkJoinTasks employ only methods fork
+ * and join
, or derivatives such as
+ * invokeAll
. However, this class also provides a number
+ * of other methods that can come into play in advanced usages, as
+ * well as extension mechanics that allow support of new forms of
+ * fork/join processing.
+ *
+ *
A ForkJoinTask is a lightweight form of {@link Future}. The
+ * efficiency of ForkJoinTasks stems from a set of restrictions (that
+ * are only partially statically enforceable) reflecting their
+ * intended use as computational tasks calculating pure functions or
+ * operating on purely isolated objects. The primary coordination
+ * mechanisms are {@link #fork}, that arranges asynchronous execution,
+ * and {@link #join}, that doesn't proceed until the task's result has
+ * been computed. Computations should avoid synchronized
+ * methods or blocks, and should minimize other blocking
+ * synchronization apart from joining other tasks or using
* synchronizers such as Phasers that are advertised to cooperate with
* fork/join scheduling. Tasks should also not perform blocking IO,
* and should ideally access variables that are completely independent
@@ -38,44 +46,54 @@ import java.lang.reflect.*;
* restrictions, for example using shared output streams, may be
* tolerable in practice, but frequent use may result in poor
* performance, and the potential to indefinitely stall if the number
- * of threads not waiting for external synchronization becomes
- * exhausted. This usage restriction is in part enforced by not
- * permitting checked exceptions such as IOExceptions to be
- * thrown. However, computations may still encounter unchecked
+ * of threads not waiting for IO or other external synchronization
+ * becomes exhausted. This usage restriction is in part enforced by
+ * not permitting checked exceptions such as IOExceptions
+ * to be thrown. However, computations may still encounter unchecked
* exceptions, that are rethrown to callers attempting join
* them. These exceptions may additionally include
* RejectedExecutionExceptions stemming from internal resource
* exhaustion such as failure to allocate internal task queues.
*
- *
The ForkJoinTask class is not usually directly - * subclassed. Instead, you subclass one of the abstract classes that - * support different styles of fork/join processing. Normally, a - * concrete ForkJoinTask subclass declares fields comprising its - * parameters, established in a constructor, and then defines a - * compute method that somehow uses the control methods - * supplied by this base class. While these methods have - * public access, some of them may only be called from within - * other ForkJoinTasks. Attempts to invoke them in other contexts - * result in exceptions or errors including ClassCastException. The - * only way to invoke a "main" driver task is to submit it to a - * ForkJoinPool. Once started, this will usually in turn start other - * subtasks. + *
The primary method for awaiting completion and extracting
+ * results of a task is {@link #join}, but there are several variants:
+ * The {@link Future#get} methods support interruptible and/or timed
+ * waits for completion and report results using Future
+ * conventions. Method {@link #helpJoin} enables callers to actively
+ * 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 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 invokeAll
(available in multiple versions)
+ * performs the most common form of parallel invocation: forking a set
+ * of tasks and joining them all.
+ *
+ *
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. Normally, a concrete
+ * ForkJoinTask subclass declares fields comprising its parameters,
+ * established in a constructor, and then defines a compute
+ * method that somehow uses the control methods supplied by this base
+ * class. While these methods have public
access (to allow
+ * instances of different task subclasses to call each others
+ * methods), some of them may only be called from within other
+ * ForkJoinTasks. Attempts to invoke them in other contexts result in
+ * exceptions or errors including ClassCastException.
*
- *
Most base support methods are final because their + *
Most base support methods are 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 protected methods exec,
- * setRawResult, and getRawResult, while also
- * introducing an abstract computational method that can be
- * implemented in its subclasses. To support such extensions,
- * instances of ForkJoinTasks maintain an atomically updated
- * short representing user-defined control state. Control
- * state is guaranteed initially to be zero, and to be negative upon
- * completion, but may otherwise be used for any other control
- * purposes, such as maintaining join counts. The {@link
- * ForkJoinWorkerThread} class supports additional inspection and
- * tuning methods that can be useful when developing extensions.
+ * minimally implement protected
methods
+ * exec
, setRawResult
, and
+ * getRawResult
, while also introducing an abstract
+ * computational method that can be implemented in its subclasses,
+ * possibly relying on other protected
methods provided
+ * by this class.
*
*
ForkJoinTasks should perform relatively small amounts of * computations, othewise splitting into smaller tasks. As a very @@ -84,19 +102,18 @@ import java.lang.reflect.*; * parellelism cannot improve throughput. If too small, then memory * and internal task maintenance overhead may overwhelm processing. * - *
ForkJoinTasks are Serializable, which enables them to - * be used in extensions such as remote execution frameworks. However, - * it is in general safe to serialize tasks only before or after, but + *
ForkJoinTasks are This method is designed to be invoked by other
* tasks. To terminate the current task, you can just return or
* throw an unchecked exception from its computation method, or
- * invoke completeExceptionally(someException).
+ * invoke 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.
*/
public abstract class ForkJoinTaskget
in that abnormal
* completion results in RuntimeExceptions or Errors, not
* ExecutionExceptions.
*
@@ -496,25 +501,8 @@ public abstract class ForkJoinTaskisDone
holds for
+ * both of them or an exception is encountered. This method may be
+ * invoked only from within ForkJoinTask computations. Attempts to
+ * invoke in other contexts result in exceptions or errors
+ * including ClassCastException.
+ * @param t1 one task
+ * @param t2 the other task
+ * @throws NullPointerException if t1 or t2 are null
+ * @throws RuntimeException or Error if either task did so.
*/
- public final void quietlyJoin() {
- if (status >= 0) {
- ForkJoinWorkerThread w = getWorker();
- if (w == null || !w.unpushTask(this) || !tryQuietlyInvoke())
- awaitDone(w, true);
- }
+ public static void invokeAll(ForkJoinTask>t1, ForkJoinTask> t2) {
+ t2.fork();
+ t1.invoke();
+ t2.join();
}
/**
- * Possibly executes other tasks until this task is ready.
+ * Forks the given tasks, returning when isDone
holds
+ * for all of them. If any task encounters an exception, others
+ * may be cancelled. This method may be invoked only from within
+ * ForkJoinTask computations. Attempts to invoke in other contexts
+ * result in exceptions or errors including ClassCastException.
+ * @param tasks the array of tasks
+ * @throws NullPointerException if tasks or any element are null.
+ * @throws RuntimeException or Error if any task did so.
*/
- public final void quietlyHelpJoin() {
- if (status >= 0) {
- ForkJoinWorkerThread w =
- (ForkJoinWorkerThread)(Thread.currentThread());
- if (!w.unpushTask(this) || !tryQuietlyInvoke())
- w.helpJoinTask(this);
+ public static void invokeAll(ForkJoinTask>... tasks) {
+ Throwable ex = null;
+ int last = tasks.length - 1;
+ for (int i = last; i >= 0; --i) {
+ ForkJoinTask> t = tasks[i];
+ if (t == null) {
+ if (ex == null)
+ ex = new NullPointerException();
+ }
+ else if (i != 0)
+ t.fork();
+ else {
+ t.quietlyInvoke();
+ if (ex == null)
+ ex = t.getException();
+ }
}
+ for (int i = 1; i <= last; ++i) {
+ ForkJoinTask> t = tasks[i];
+ if (t != null) {
+ if (ex != null)
+ t.cancel(false);
+ else {
+ t.quietlyJoin();
+ if (ex == null)
+ ex = t.getException();
+ }
+ }
+ }
+ if (ex != null)
+ rethrowException(ex);
}
/**
- * Performs this task and awaits its completion if necessary,
- * without returning its result or throwing an exception. This
- * method may be useful when processing collections of tasks when
- * some have been cancelled or otherwise known to have aborted.
+ * Forks all tasks in the collection, returning when
+ * isDone
holds for all of them. If any task
+ * encounters an exception, others may be cancelled. This method
+ * may be invoked only from within ForkJoinTask
+ * computations. Attempts to invoke in other contexts resul!t in
+ * exceptions or errors including ClassCastException.
+ * @param tasks the collection of tasks
+ * @throws NullPointerException if tasks or any element are null.
+ * @throws RuntimeException or Error if any task did so.
*/
- public final void quietlyInvoke() {
- if (status >= 0 && !tryQuietlyInvoke())
- quietlyJoin();
+ public static void invokeAll(Collection extends ForkJoinTask>> tasks) {
+ if (!(tasks instanceof List)) {
+ invokeAll(tasks.toArray(new ForkJoinTask[tasks.size()]));
+ return;
+ }
+ List extends ForkJoinTask>> ts =
+ (List extends ForkJoinTask>>)tasks;
+ Throwable ex = null;
+ int last = ts.size() - 1;
+ for (int i = last; i >= 0; --i) {
+ ForkJoinTask> t = ts.get(i);
+ if (t == null) {
+ if (ex == null)
+ ex = new NullPointerException();
+ }
+ else if (i != 0)
+ t.fork();
+ else {
+ t.quietlyInvoke();
+ if (ex == null)
+ ex = t.getException();
+ }
+ }
+ for (int i = 1; i <= last; ++i) {
+ ForkJoinTask> t = ts.get(i);
+ if (t != null) {
+ if (ex != null)
+ t.cancel(false);
+ else {
+ t.quietlyJoin();
+ if (ex == null)
+ ex = t.getException();
+ }
+ }
+ }
+ if (ex != null)
+ rethrowException(ex);
}
/**
@@ -584,7 +645,7 @@ public abstract class ForkJoinTaskisCancelled
+ * will report true, and join
will result in a
+ * CancellationException
being thrown. Otherwise, when
* cancellation races with completion, there are no guarantees
- * about whether isCancelled will report true, whether
- * join will return normally or via an exception, or
+ * about whether isCancelled
will report true, whether
+ * join
will return normally or via an exception, or
* whether these behaviors will remain consistent upon repeated
* invocation.
*
@@ -622,7 +683,7 @@ public abstract class ForkJoinTaskcompleteExceptionally
.
*
* @param mayInterruptIfRunning this value is ignored in the
* default implementation because tasks are not in general
@@ -638,11 +699,13 @@ public abstract class ForkJoinTaskjoin
and related operations. This method may be used
* to induce exceptions in asynchronous tasks, or to force
- * completion of tasks that would not otherwise complete. This
- * method is overridable, but overridden versions must invoke
- * super implementation to maintain guarantees.
+ * completion of tasks that would not otherwise complete. Its use
+ * in other situations is likely to be wrong. This method is
+ * overridable, but overridden versions must invoke super
+ * implementation to maintain guarantees.
+ *
* @param ex the exception to throw. If this exception is
* not a RuntimeException or Error, the actual exception thrown
* will be a RuntimeException with cause ex.
@@ -655,10 +718,13 @@ public abstract class ForkJoinTasknull
result upon join
and related
* operations. This method may be used to provide results for
* asynchronous tasks, or to provide alternative handling for
- * tasks that would not otherwise complete normally.
+ * tasks that would not otherwise complete normally. Its use in
+ * other situations is likely to be wrong. This method is
+ * overridable, but overridden versions must invoke super
+ * implementation to maintain guarantees.
*
* @param value the result value for this task.
*/
@@ -673,8 +739,68 @@ public abstract class ForkJoinTaskjoin
, but is only applicable when
+ * there are no potemtial 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
+ * ForkJoinTask computations. Attempts to invoke in other contexts
+ * resul!t in exceptions or errors including ClassCastException.
+ * @return the computed result
+ */
+ public final V helpJoin() {
+ ForkJoinWorkerThread w = (ForkJoinWorkerThread)(Thread.currentThread());
+ if (status < 0 || !w.unpushTask(this) || !tryExec())
+ reportException(w.helpJoinTask(this));
+ return getRawResult();
+ }
+
+ /**
+ * Possibly executes other tasks until this task is ready. This
+ * method may be invoked only from within ForkJoinTask
+ * computations. Attempts to invoke in other contexts resul!t in
+ * exceptions or errors including ClassCastException.
+ */
+ public final void quietlyHelpJoin() {
+ if (status >= 0) {
+ ForkJoinWorkerThread w =
+ (ForkJoinWorkerThread)(Thread.currentThread());
+ if (!w.unpushTask(this) || !tryQuietlyInvoke())
+ w.helpJoinTask(this);
+ }
+ }
+
+ /**
+ * Joins this task, without returning its result or throwing an
+ * exception. This method may be useful when processing
+ * collections of tasks when some have been cancelled or otherwise
+ * known to have aborted.
+ */
+ public final void quietlyJoin() {
+ if (status >= 0) {
+ ForkJoinWorkerThread w = getWorker();
+ if (w == null || !w.unpushTask(this) || !tryQuietlyInvoke())
+ awaitDone(w, true);
+ }
+ }
+
+ /**
+ * Commences performing this task and awaits its completion if
+ * necessary, without returning its result or throwing an
+ * exception. This method may be useful when processing
+ * collections of tasks when some have been cancelled or otherwise
+ * known to have aborted.
+ */
+ public final void quietlyInvoke() {
+ if (status >= 0 && !tryQuietlyInvoke())
+ quietlyJoin();
+ }
+
+ /**
* Resets the internal bookkeeping state of this task, allowing a
- * subsequent fork. This method allows repeated reuse of
+ * subsequent fork
. This method allows repeated reuse of
* this task, but only if reuse occurs when this task has either
* never been forked, or has been forked, then completed and all
* outstanding joins of this task have also completed. Effects
@@ -689,126 +815,29 @@ public abstract class ForkJoinTaskjoin
,
+ * even if this task completed abnormally, or null if this task is
+ * not known to have been completed. This method is designed to
+ * aid debugging, as well as to support extensions. Its use in any
+ * other context is discouraged.
*
* @return the result, or null if not completed.
*/
@@ -865,13 +907,56 @@ public abstract class ForkJoinTaskcomplete
to become joinable. It may throw exceptions
* to indicate abnormal exit.
* @return true if completed normally
* @throws Error or RuntimeException if encountered during computation
*/
protected abstract boolean exec();
+ /**
+ * Returns, but does not unschedule or execute, the task most
+ * recently forked by the current thread but not yet executed, if
+ * one is available. There is no guarantee that this task will
+ * actually be polled or executed next.
+ * This method is designed primarily to support extensions,
+ * and is unlikely to be useful otherwise.
+ *
+ * @return the next task, or null if none are available
+ */
+ protected static ForkJoinTask> peekNextLocalTask() {
+ return ((ForkJoinWorkerThread)(Thread.currentThread())).peekTask();
+ }
+
+ /**
+ * Unschedules and returns, without executing, the task most
+ * recently forked by the current thread but not yet executed.
+ * This method is designed primarily to support extensions,
+ * and is unlikely to be useful otherwise.
+ *
+ * @return the next task, or null if none are available
+ */
+ protected static ForkJoinTask> pollNextLocalTask() {
+ return ((ForkJoinWorkerThread)(Thread.currentThread())).popTask();
+ }
+
+ /**
+ * Unschedules and returns, without executing, the task most
+ * recently forked by the current thread but not yet executed, if
+ * one is available, or if not available, a task that was forked
+ * by some other thread, if available. Availability may be
+ * transient, so a null
result does not necessarily
+ * imply quiecence of the pool this task is operating in.
+ * This method is designed primarily to support extensions,
+ * and is unlikely to be useful otherwise.
+ *
+ * @return a task, or null if none are available
+ */
+ protected static ForkJoinTask> pollTask() {
+ return ((ForkJoinWorkerThread)(Thread.currentThread())).
+ getLocalOrStolenTask();
+ }
+
// Serialization support
private static final long serialVersionUID = -7721805057305804111L;
@@ -896,7 +981,8 @@ public abstract class ForkJoinTask