--- jsr166/src/jsr166y/ForkJoinTask.java 2009/07/21 18:11:44 1.11 +++ jsr166/src/jsr166y/ForkJoinTask.java 2009/08/04 20:24:54 1.37 @@ -5,55 +5,60 @@ */ 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 {@link - * ForkJoinPool}. A ForkJoinTask is a thread-like entity that is much + * 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. * - *
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 {@code fork} - * and {@code join}, or derivatives such as - * {@code 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 "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. * - *
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 {@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 join - * them. These exceptions may additionally include - * RejectedExecutionExceptions stemming from internal resource - * exhaustion such as failure to allocate internal task queues. + *
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. * *
The primary method for awaiting completion and extracting * results of a task is {@link #join}, but there are several variants: @@ -63,50 +68,76 @@ import java.lang.reflect.*; * 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 ForkJoinTask class is not usually directly subclassed. + *
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 #isCancelled} is true if completion was due to cancellation; + * {@link #isCompletedNormally} is true if a task completed without + * cancellation or encountering an exception; {@link + * #isCompletedExceptionally} is true if if the task encountered an + * exception (in which case {@link #getException} returns the + * 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. + * + *
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 + * 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 others + * instances of different task subclasses to call each other's * 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. + * 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 - * {@code exec}, {@code setRawResult}, and - * {@code 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 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 + * 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
- * in general 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 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
*/
- public static void invokeAll(ForkJoinTask>t1, ForkJoinTask> t2) {
+ public static void invokeAll(ForkJoinTask> t1, ForkJoinTask> t2) {
t2.fork();
t1.invoke();
t2.join();
}
/**
- * Forks the given tasks, returning when {@code 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.
+ * 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 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
+ * {@link #inForkJoinPool}). Attempts to invoke in other contexts
+ * result in exceptions or errors, possibly including {@code
+ * 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
+ * @param tasks the tasks
+ * @throws NullPointerException if any task is null
*/
public static void invokeAll(ForkJoinTask>... tasks) {
Throwable ex = null;
@@ -579,24 +633,35 @@ 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}.
*
* @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 void invokeAll(Collection extends ForkJoinTask>> tasks) {
- if (!(tasks instanceof List)) {
- invokeAll(tasks.toArray(new ForkJoinTask[tasks.size()]));
- return;
+ public static This method may be overridden in subclasses, but if so, must
+ * still ensure that these minimal properties hold. In particular,
+ * the {@code cancel} method itself must not throw exceptions.
+ *
+ * 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 {@link #completeExceptionally}.
+ *
+ * @param mayInterruptIfRunning this value is ignored in the
+ * default implementation because tasks are not
+ * cancelled via interruption
+ *
+ * @return {@code true} if this task is now cancelled
+ */
+ public boolean cancel(boolean mayInterruptIfRunning) {
+ setCompletion(CANCELLED);
+ return (status & COMPLETION_MASK) == CANCELLED;
}
/**
- * Returns true if the computation performed by this task has
- * completed (or has been cancelled).
+ * Returns {@code true} if the computation performed by this task
+ * has completed (or has been cancelled).
*
- * @return true if this computation has completed
+ * @return {@code true} if this computation has completed
*/
public final boolean isDone() {
return status < 0;
}
/**
- * Returns true if this task was cancelled.
+ * Returns {@code true} if this task was cancelled.
*
- * @return 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, then execution will be suppressed, {@code isCancelled}
- * will report true, and {@code 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 true, whether
- * {@code join} will return normally or via an exception, or
- * whether these behaviors will remain consistent upon repeated
- * invocation.
+ * Returns {@code true} if this task threw an exception or was cancelled.
*
- * 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.
- *
- * 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 {@code completeExceptionally}.
- *
- * @param mayInterruptIfRunning this value is ignored in the
- * default implementation because tasks are not in general
- * cancelled via interruption.
+ * @return {@code true} if this task threw an exception or was cancelled
+ */
+ public final boolean isCompletedAbnormally() {
+ return (status & COMPLETION_MASK) < NORMAL;
+ }
+
+ /**
+ * Returns {@code true} if this task completed without throwing an
+ * exception and was not cancelled.
*
- * @return true if this task is now cancelled
+ * @return {@code true} if this task completed without throwing an
+ * exception and was not cancelled
*/
- public boolean cancel(boolean mayInterruptIfRunning) {
- setCompletion(CANCELLED);
- return (status & COMPLETION_MASK) == CANCELLED;
+ public final boolean isCompletedNormally() {
+ return (status & COMPLETION_MASK) == NORMAL;
}
/**
- * Returns true if this task threw an exception or was cancelled.
+ * Returns {@code true} if this task threw an exception.
*
- * @return true if this task threw an exception or was cancelled
+ * @return {@code true} if this task threw an exception
*/
- public final boolean isCompletedAbnormally() {
- return (status & COMPLETION_MASK) < NORMAL;
+ public final boolean isCompletedExceptionally() {
+ return (status & COMPLETION_MASK) == EXCEPTIONAL;
}
/**
* Returns the exception thrown by the base computation, or a
- * CancellationException if cancelled, or null if none or if the
- * method has not yet completed.
+ * {@code CancellationException} if cancelled, or {@code null} if
+ * none or if the method has not yet completed.
*
- * @return the exception, or null if none
+ * @return the exception, or {@code null} if none
*/
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));
}
/**
@@ -711,7 +792,7 @@ 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());
+ ForkJoinWorkerThread w = (ForkJoinWorkerThread) Thread.currentThread();
if (status < 0 || !w.unpushTask(this) || !tryExec())
reportException(busyJoin(w));
return getRawResult();
@@ -784,14 +870,19 @@ 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}.
*/
public final void quietlyHelpJoin() {
if (status >= 0) {
ForkJoinWorkerThread w =
- (ForkJoinWorkerThread)(Thread.currentThread());
+ (ForkJoinWorkerThread) Thread.currentThread();
if (!w.unpushTask(this) || !tryQuietlyInvoke())
busyJoin(w);
}
@@ -825,13 +916,20 @@ 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}.
*/
public static void helpQuiesce() {
- ((ForkJoinWorkerThread)(Thread.currentThread())).
- helpQuiescePool();
+ ((ForkJoinWorkerThread) Thread.currentThread())
+ .helpQuiescePool();
}
/**
@@ -840,8 +938,8 @@ 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 true if unforked
+ * @return {@code true} if unforked
*/
public boolean tryUnfork() {
- return ((ForkJoinWorkerThread)(Thread.currentThread())).unpushTask(this);
+ return ((ForkJoinWorkerThread) Thread.currentThread())
+ .unpushTask(this);
}
/**
@@ -884,11 +999,17 @@ 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 number of tasks
*/
public static int getQueuedTaskCount() {
- return ((ForkJoinWorkerThread)(Thread.currentThread())).
- getQueueSize();
+ return ((ForkJoinWorkerThread) Thread.currentThread())
+ .getQueueSize();
}
/**
@@ -901,23 +1022,29 @@ 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 surplus number of tasks, which may be negative
*/
public static int getSurplusQueuedTaskCount() {
- return ((ForkJoinWorkerThread)(Thread.currentThread()))
+ return ((ForkJoinWorkerThread) Thread.currentThread())
.getEstimatedSurplusTaskCount();
}
// Extension methods
/**
- * Returns the result that would be returned by {@code 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.
+ * 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();
@@ -936,43 +1063,53 @@ 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 null if none are available
+ * @return the next task, or {@code null} if none are available
*/
protected static ForkJoinTask> peekNextLocalTask() {
- return ((ForkJoinWorkerThread)(Thread.currentThread())).peekTask();
+ 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.
+ * be useful otherwise.
*
- * @return the next task, or null if none are available
+ * 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();
+ return ((ForkJoinWorkerThread) Thread.currentThread())
+ .pollLocalTask();
}
/**
@@ -983,16 +1120,112 @@ 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 a task, or null if none are available
+ * @return a task, or {@code null} if none are available
*/
protected static ForkJoinTask> pollTask() {
- return ((ForkJoinWorkerThread)(Thread.currentThread())).
- 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