--- jsr166/src/jsr166y/ForkJoinTask.java 2009/01/06 14:30:31 1.1 +++ jsr166/src/jsr166y/ForkJoinTask.java 2009/08/03 13:01:15 1.32 @@ -5,98 +5,132 @@ */ package jsr166y; -import java.io.Serializable; -import java.util.*; + import java.util.concurrent.*; -import java.util.concurrent.atomic.*; -import sun.misc.Unsafe; -import java.lang.reflect.*; + +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; /** - * 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 {@code 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 - * 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 - * of those accessed by other running tasks. Minor breaches of these - * 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 - * 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. + *
A "main" {@code 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 {@code ForkJoinTask} employ only methods + * {@link #fork} and {@link #join}, or derivatives such as {@link + * #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. * - *
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. + *
A {@code ForkJoinTask} is a lightweight form of {@link Future}. + * The efficiency of {@code ForkJoinTask}s 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 {@code 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 of those accessed by other running + * tasks. Minor breaches of these 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 IO or + * other external synchronization becomes exhausted. This usage + * 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 to join them. These exceptions may + * additionally include RejectedExecutionExceptions stemming from + * internal resource exhaustion such as failure to allocate internal + * task queues. * - *
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. + *
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 {@code 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 {@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 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 + * RecursiveAction} for computations that do not return results, or + * {@link RecursiveTask} for those that do. Normally, a concrete + * ForkJoinTask subclass declares fields comprising its parameters, + * 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 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}, 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, othewise 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 - * parellelism 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}. * - *
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 - * 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
*/
public abstract class ForkJoinTask This method may be invoked only from within {@code
+ * ForkJoinTask} computations (as may be determined using method
+ * {@link #inForkJoinPool}). Attempts to invoke in other contexts
+ * result in exceptions or errors, possibly including {@code
+ * ClassCastException}.
+ *
+ * @return {@code this}, to simplify usage
*/
- public final void fork() {
- ((ForkJoinWorkerThread)(Thread.currentThread())).pushTask(this);
+ public final ForkJoinTask This method may be invoked only from within {@code
+ * ForkJoinTask} computations (as may be determined using method
+ * {@link #inForkJoinPool}). Attempts to invoke in other contexts
+ * result in exceptions or errors, possibly including {@code
+ * ClassCastException}.
+ *
+ * @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 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 {@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.
+ *
+ * This method may be invoked only from within {@code
+ * ForkJoinTask} computations (as may be determined using method
+ * {@link #inForkJoinPool}). Attempts to invoke in other contexts
+ * result in exceptions or errors, possibly including {@code
+ * ClassCastException}.
+ *
+ * @param tasks the 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.
- */
- public final void quietlyInvoke() {
- if (status >= 0 && !tryQuietlyInvoke())
- quietlyJoin();
+ * Forks all tasks in the specified 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. 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
+ * {@link #inForkJoinPool}). Attempts to invoke in other contexts
+ * result in exceptions or errors, possibly including {@code
+ * ClassCastException}.
+ *
+ * @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 This method may be overridden in subclasses, but if so, must
* still ensure that these minimal properties hold. In particular,
- * the cancel method itself must not throw exceptions.
+ * the {@code cancel} method itself must not throw exceptions.
*
- * This method is designed to be invoked by other
+ * 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 {@link #completeExceptionally}.
*
* @param mayInterruptIfRunning this value is ignored in the
* default implementation because tasks are not in general
- * cancelled via interruption.
+ * cancelled via interruption
*
- * @return true if this task is now cancelled
+ * @return {@code true} if this task is now cancelled
*/
public boolean cancel(boolean mayInterruptIfRunning) {
setCompletion(CANCELLED);
@@ -636,50 +724,183 @@ public abstract class ForkJoinTask This method may be invoked only from within {@code
+ * ForkJoinTask} computations (as may be determined using method
+ * {@link #inForkJoinPool}). Attempts to invoke in other contexts
+ * result in exceptions or errors, possibly including {@code
+ * ClassCastException}.
+ *
+ * @return the computed result
+ */
+ public final V helpJoin() {
+ ForkJoinWorkerThread w = (ForkJoinWorkerThread) Thread.currentThread();
+ if (status < 0 || !w.unpushTask(this) || !tryExec())
+ reportException(busyJoin(w));
+ return getRawResult();
+ }
+
+ /**
+ * Possibly executes other tasks until this task is ready. 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
+ * {@link #inForkJoinPool}). Attempts to invoke in other contexts
+ * result in exceptions or errors, possibly including {@code
+ * ClassCastException}.
+ */
+ public final void quietlyHelpJoin() {
+ if (status >= 0) {
+ ForkJoinWorkerThread w =
+ (ForkJoinWorkerThread) Thread.currentThread();
+ if (!w.unpushTask(this) || !tryQuietlyInvoke())
+ busyJoin(w);
+ }
+ }
+
+ /**
+ * 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();
+ }
+
+ /**
+ * 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.
+ *
+ * This method may be invoked only from within {@code
+ * ForkJoinTask} computations (as may be determined using method
+ * {@link #inForkJoinPool}). Attempts to invoke in other contexts
+ * result in exceptions or errors, possibly including {@code
+ * ClassCastException}.
+ */
+ public static void helpQuiesce() {
+ ((ForkJoinWorkerThread) Thread.currentThread())
+ .helpQuiescePool();
+ }
+
/**
* Resets the internal bookkeeping state of this task, allowing a
- * subsequent fork. This method allows repeated reuse of
+ * subsequent {@code 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
- * under any other usage conditions are not guaranteed, and are
- * almost surely wrong. This method may be useful when executing
+ * under any other usage conditions are not guaranteed.
+ * This method may be useful when executing
* pre-constructed trees of subtasks in loops.
*/
public void reinitialize() {
@@ -689,164 +910,102 @@ public abstract class ForkJoinTask This method may be invoked only from within {@code
+ * ForkJoinTask} computations (as may be determined using method
+ * {@link #inForkJoinPool}). Attempts to invoke in other contexts
+ * result in exceptions or errors, possibly including {@code
+ * ClassCastException}.
+ *
+ * @return {@code true} if unforked
*/
- 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 boolean tryUnfork() {
+ return ((ForkJoinWorkerThread) Thread.currentThread())
+ .unpushTask(this);
}
/**
- * 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.
+ * 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.
+ *
+ * This method may be invoked only from within {@code
+ * ForkJoinTask} computations (as may be determined using method
+ * {@link #inForkJoinPool}). Attempts to invoke in other contexts
+ * result in exceptions or errors, possibly including {@code
+ * ClassCastException}.
+ *
+ * @return the number of tasks
*/
- public static void helpQuiesce() {
- ((ForkJoinWorkerThread)(Thread.currentThread())).
- helpQuiescePool();
+ public static int getQueuedTaskCount() {
+ return ((ForkJoinWorkerThread) Thread.currentThread())
+ .getQueueSize();
}
/**
- * Returns a estimate of how many more locally queued tasks are
+ * Returns an 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.
+ *
+ * This method may be invoked only from within {@code
+ * ForkJoinTask} computations (as may be determined using method
+ * {@link #inForkJoinPool}). Attempts to invoke in other contexts
+ * result in exceptions or errors, possibly including {@code
+ * ClassCastException}.
+ *
* @return the surplus number of tasks, which may be negative
*/
- public static int surplus() {
- return ((ForkJoinWorkerThread)(Thread.currentThread()))
+ 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 {@link #join}, even
+ * if this task completed abnormally, or {@code 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.
+ * @return the result, or {@code null} if not completed
*/
public abstract V getRawResult();
@@ -865,13 +1024,172 @@ public abstract class ForkJoinTask This method may be invoked only from within {@code
+ * ForkJoinTask} computations (as may be determined using method
+ * {@link #inForkJoinPool}). Attempts to invoke in other contexts
+ * result in exceptions or errors, possibly including {@code
+ * ClassCastException}.
+ *
+ * @return the next task, or {@code 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 {@code
+ * ForkJoinTask} computations (as may be determined using method
+ * {@link #inForkJoinPool}). Attempts to invoke in other contexts
+ * result in exceptions or errors, possibly including {@code
+ * ClassCastException}.
+ *
+ * @return the next task, or {@code 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
+ * {@code null} result does not necessarily imply quiescence
+ * 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 {@code
+ * ForkJoinTask} computations (as may be determined using method
+ * {@link #inForkJoinPool}). Attempts to invoke in other contexts
+ * result in exceptions or errors, possibly including {@code
+ * ClassCastException}.
+ *
+ * @return a task, or {@code null} if none are available
+ */
+ protected static ForkJoinTask> pollTask() {
+ return ((ForkJoinWorkerThread) Thread.currentThread())
+ .pollTask();
+ }
+
+ /**
+ * Adaptor for Runnables. This implements RunnableFuture
+ * to be compliant with AbstractExecutorService constraints
+ * when used in ForkJoinPool.
+ */
+ static final class AdaptedRunnable