--- jsr166/src/jsr166y/ForkJoinTask.java 2009/01/06 14:30:31 1.1 +++ jsr166/src/jsr166y/ForkJoinTask.java 2009/07/20 21:45:06 1.7 @@ -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. + * 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. * - *
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 + *
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 possibly 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.
*
@@ -480,41 +496,9 @@ 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
+ * possibly 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 possibly 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 possibly 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);
}
/**
@@ -581,37 +638,14 @@ 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 +656,7 @@ public abstract class ForkJoinTaskcompleteExceptionally
.
*
* @param mayInterruptIfRunning this value is ignored in the
* default implementation because tasks are not in general
@@ -636,13 +670,38 @@ 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 +714,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.
*/
@@ -672,143 +734,79 @@ 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 possibly including ClassCastException.
+ * @return the computed result
*/
- public boolean tryUnfork() {
- return ((ForkJoinWorkerThread)(Thread.currentThread())).unpushTask(this);
+ public final V helpJoin() {
+ ForkJoinWorkerThread w = (ForkJoinWorkerThread)(Thread.currentThread());
+ if (status < 0 || !w.unpushTask(this) || !tryExec())
+ reportException(busyJoin(w));
+ return getRawResult();
}
/**
- * Forks both tasks, returning when isDone holds for both
- * of them or an exception is encountered. This method may be
- * invoked only from within other 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.
+ * 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 possibly including ClassCastException.
*/
- public static void invokeAll(ForkJoinTask>t1, ForkJoinTask> t2) {
- t2.fork();
- t1.invoke();
- t2.join();
+ public final void quietlyHelpJoin() {
+ if (status >= 0) {
+ ForkJoinWorkerThread w =
+ (ForkJoinWorkerThread)(Thread.currentThread());
+ if (!w.unpushTask(this) || !tryQuietlyInvoke())
+ busyJoin(w);
+ }
}
/**
- * 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 other
- * 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.
+ * 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 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();
- }
- }
+ public final void quietlyJoin() {
+ if (status >= 0) {
+ ForkJoinWorkerThread w = getWorker();
+ if (w == null || !w.unpushTask(this) || !tryQuietlyInvoke())
+ awaitDone(w, true);
}
- if (ex != null)
- rethrowException(ex);
}
/**
- * 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 other ForkJoinTask
- * computations. Attempts to invoke in other contexts result 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.
+ * 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 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);
+ public final void quietlyInvoke() {
+ if (status >= 0 && !tryQuietlyInvoke())
+ quietlyJoin();
}
/**
@@ -823,28 +821,83 @@ public abstract class ForkJoinTaskfork
. 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
+ * under any other usage conditions are not guaranteed, and are
+ * almost surely wrong. This method may be useful when executing
+ * pre-constructed trees of subtasks in loops.
+ */
+ public void reinitialize() {
+ if ((status & COMPLETION_MASK) == EXCEPTIONAL)
+ exceptionMap.remove(this);
+ status = 0;
+ }
+
+ /**
+ * Returns the pool hosting the current task execution, or null
+ * if this task is executing outside of any pool.
+ * @return the pool, or null if none.
+ */
+ public static ForkJoinPool getPool() {
+ Thread t = Thread.currentThread();
+ return ((t instanceof ForkJoinWorkerThread)?
+ ((ForkJoinWorkerThread)t).pool : null);
+ }
+
+ /**
+ * Tries to unschedule this task for execution. This method will
+ * typically succeed if this task is the most recently forked task
+ * by the current thread, and has not commenced executing in
+ * another thread. This method may be useful when arranging
+ * alternative local processing of tasks that could have been, but
+ * were not, stolen. This method may be invoked only from within
+ * ForkJoinTask computations. Attempts to invoke in other contexts
+ * result in exceptions or errors possibly including ClassCastException.
+ * @return true if unforked
+ */
+ public boolean tryUnfork() {
+ return ((ForkJoinWorkerThread)(Thread.currentThread())).unpushTask(this);
+ }
+
+ /**
+ * Returns an estimate of the number of tasks that have been
+ * forked by the current worker thread but not yet executed. This
+ * value may be useful for heuristic decisions about whether to
+ * fork other tasks.
+ * @return the number of tasks
+ */
+ public static int getQueuedTaskCount() {
+ return ((ForkJoinWorkerThread)(Thread.currentThread())).
+ getQueueSize();
+ }
+
+ /**
* Returns a estimate of how many more locally queued tasks are
* held by the current worker thread than there are other worker
- * threads that might want to steal them. This value may be
- * useful for heuristic decisions about whether to fork other
- * tasks. In many usages of ForkJoinTasks, at steady state, each
- * worker should aim to maintain a small constant surplus (for
- * example, 3) of tasks, and to process computations locally if
- * this threshold is exceeded.
+ * threads that might steal them. This value may be useful for
+ * heuristic decisions about whether to fork other tasks. In many
+ * usages of ForkJoinTasks, at steady state, each worker should
+ * aim to maintain a small constant surplus (for example, 3) of
+ * tasks, and to process computations locally if this threshold is
+ * exceeded.
* @return the surplus number of tasks, which may be negative
*/
- public static int surplus() {
+ public static int getSurplusQueuedTaskCount() {
return ((ForkJoinWorkerThread)(Thread.currentThread()))
.getEstimatedSurplusTaskCount();
}
- // Extension kit
+ // Extension methods
/**
- * Returns the result that would be returned by join, 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.
+ * Returns the result that would be returned by join
,
+ * 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 +918,64 @@ 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 queued 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.
+ * This method may be invoked only from within ForkJoinTask
+ * computations. Attempts to invoke in other contexts result in
+ * exceptions or errors possibly including ClassCastException.
+ *
+ * @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 next task
+ * queued by the current thread but not yet executed. This method
+ * is designed primarily to support extensions, and is unlikely to
+ * be useful otherwise. This method may be invoked only from
+ * within ForkJoinTask computations. Attempts to invoke in other
+ * contexts result in exceptions or errors possibly including
+ * ClassCastException.
+ *
+ * @return the next task, or null if none are available
+ */
+ protected static ForkJoinTask> pollNextLocalTask() {
+ return ((ForkJoinWorkerThread)(Thread.currentThread())).pollLocalTask();
+ }
+
+ /**
+ * Unschedules and returns, without executing, the next task
+ * queued 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. This method may be invoked only from within
+ * ForkJoinTask computations. Attempts to invoke in other contexts
+ * result in exceptions or errors possibly including
+ * ClassCastException.
+ *
+ * @return a task, or null if none are available
+ */
+ protected static ForkJoinTask> pollTask() {
+ return ((ForkJoinWorkerThread)(Thread.currentThread())).
+ pollTask();
+ }
+
// Serialization support
private static final long serialVersionUID = -7721805057305804111L;
@@ -896,29 +1000,53 @@ public abstract class ForkJoinTask