jaroslav@1890: /* jaroslav@1890: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. jaroslav@1890: * jaroslav@1890: * This code is free software; you can redistribute it and/or modify it jaroslav@1890: * under the terms of the GNU General Public License version 2 only, as jaroslav@1890: * published by the Free Software Foundation. Oracle designates this jaroslav@1890: * particular file as subject to the "Classpath" exception as provided jaroslav@1890: * by Oracle in the LICENSE file that accompanied this code. jaroslav@1890: * jaroslav@1890: * This code is distributed in the hope that it will be useful, but WITHOUT jaroslav@1890: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or jaroslav@1890: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License jaroslav@1890: * version 2 for more details (a copy is included in the LICENSE file that jaroslav@1890: * accompanied this code). jaroslav@1890: * jaroslav@1890: * You should have received a copy of the GNU General Public License version jaroslav@1890: * 2 along with this work; if not, write to the Free Software Foundation, jaroslav@1890: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. jaroslav@1890: * jaroslav@1890: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA jaroslav@1890: * or visit www.oracle.com if you need additional information or have any jaroslav@1890: * questions. jaroslav@1890: */ jaroslav@1890: jaroslav@1890: /* jaroslav@1890: * This file is available under and governed by the GNU General Public jaroslav@1890: * License version 2 only, as published by the Free Software Foundation. jaroslav@1890: * However, the following notice accompanied the original version of this jaroslav@1890: * file: jaroslav@1890: * jaroslav@1890: * Written by Doug Lea with assistance from members of JCP JSR-166 jaroslav@1890: * Expert Group and released to the public domain, as explained at jaroslav@1890: * http://creativecommons.org/publicdomain/zero/1.0/ jaroslav@1890: */ jaroslav@1890: jaroslav@1890: package java.util.concurrent; jaroslav@1890: jaroslav@1890: import java.io.Serializable; jaroslav@1890: import java.util.Collection; jaroslav@1890: import java.util.Collections; jaroslav@1890: import java.util.List; jaroslav@1890: import java.util.RandomAccess; jaroslav@1890: import java.util.Map; jaroslav@1890: import java.lang.ref.WeakReference; jaroslav@1890: import java.lang.ref.ReferenceQueue; jaroslav@1890: import java.util.concurrent.Callable; jaroslav@1890: import java.util.concurrent.CancellationException; jaroslav@1890: import java.util.concurrent.ExecutionException; jaroslav@1890: import java.util.concurrent.Executor; jaroslav@1890: import java.util.concurrent.ExecutorService; jaroslav@1890: import java.util.concurrent.Future; jaroslav@1890: import java.util.concurrent.RejectedExecutionException; jaroslav@1890: import java.util.concurrent.RunnableFuture; jaroslav@1890: import java.util.concurrent.TimeUnit; jaroslav@1890: import java.util.concurrent.TimeoutException; jaroslav@1890: import java.util.concurrent.locks.ReentrantLock; jaroslav@1890: import java.lang.reflect.Constructor; jaroslav@1890: jaroslav@1890: /** jaroslav@1890: * Abstract base class for tasks that run within a {@link ForkJoinPool}. jaroslav@1890: * A {@code ForkJoinTask} is a thread-like entity that is much jaroslav@1890: * lighter weight than a normal thread. Huge numbers of tasks and jaroslav@1890: * subtasks may be hosted by a small number of actual threads in a jaroslav@1890: * ForkJoinPool, at the price of some usage limitations. jaroslav@1890: * jaroslav@1890: *

A "main" {@code ForkJoinTask} begins execution when submitted jaroslav@1890: * to a {@link ForkJoinPool}. Once started, it will usually in turn jaroslav@1890: * start other subtasks. As indicated by the name of this class, jaroslav@1890: * many programs using {@code ForkJoinTask} employ only methods jaroslav@1890: * {@link #fork} and {@link #join}, or derivatives such as {@link jaroslav@1890: * #invokeAll(ForkJoinTask...) invokeAll}. However, this class also jaroslav@1890: * provides a number of other methods that can come into play in jaroslav@1890: * advanced usages, as well as extension mechanics that allow jaroslav@1890: * support of new forms of fork/join processing. jaroslav@1890: * jaroslav@1890: *

A {@code ForkJoinTask} is a lightweight form of {@link Future}. jaroslav@1890: * The efficiency of {@code ForkJoinTask}s stems from a set of jaroslav@1890: * restrictions (that are only partially statically enforceable) jaroslav@1890: * reflecting their intended use as computational tasks calculating jaroslav@1890: * pure functions or operating on purely isolated objects. The jaroslav@1890: * primary coordination mechanisms are {@link #fork}, that arranges jaroslav@1890: * asynchronous execution, and {@link #join}, that doesn't proceed jaroslav@1890: * until the task's result has been computed. Computations should jaroslav@1890: * avoid {@code synchronized} methods or blocks, and should minimize jaroslav@1890: * other blocking synchronization apart from joining other tasks or jaroslav@1890: * using synchronizers such as Phasers that are advertised to jaroslav@1890: * cooperate with fork/join scheduling. Tasks should also not perform jaroslav@1890: * blocking IO, and should ideally access variables that are jaroslav@1890: * completely independent of those accessed by other running jaroslav@1890: * tasks. Minor breaches of these restrictions, for example using jaroslav@1890: * shared output streams, may be tolerable in practice, but frequent jaroslav@1890: * use may result in poor performance, and the potential to jaroslav@1890: * indefinitely stall if the number of threads not waiting for IO or jaroslav@1890: * other external synchronization becomes exhausted. This usage jaroslav@1890: * restriction is in part enforced by not permitting checked jaroslav@1890: * exceptions such as {@code IOExceptions} to be thrown. However, jaroslav@1890: * computations may still encounter unchecked exceptions, that are jaroslav@1890: * rethrown to callers attempting to join them. These exceptions may jaroslav@1890: * additionally include {@link RejectedExecutionException} stemming jaroslav@1890: * from internal resource exhaustion, such as failure to allocate jaroslav@1890: * internal task queues. Rethrown exceptions behave in the same way as jaroslav@1890: * regular exceptions, but, when possible, contain stack traces (as jaroslav@1890: * displayed for example using {@code ex.printStackTrace()}) of both jaroslav@1890: * the thread that initiated the computation as well as the thread jaroslav@1890: * actually encountering the exception; minimally only the latter. jaroslav@1890: * jaroslav@1890: *

The primary method for awaiting completion and extracting jaroslav@1890: * results of a task is {@link #join}, but there are several variants: jaroslav@1890: * The {@link Future#get} methods support interruptible and/or timed jaroslav@1890: * waits for completion and report results using {@code Future} jaroslav@1890: * conventions. Method {@link #invoke} is semantically jaroslav@1890: * equivalent to {@code fork(); join()} but always attempts to begin jaroslav@1890: * execution in the current thread. The "quiet" forms of jaroslav@1890: * these methods do not extract results or report exceptions. These jaroslav@1890: * may be useful when a set of tasks are being executed, and you need jaroslav@1890: * to delay processing of results or exceptions until all complete. jaroslav@1890: * Method {@code invokeAll} (available in multiple versions) jaroslav@1890: * performs the most common form of parallel invocation: forking a set jaroslav@1890: * of tasks and joining them all. jaroslav@1890: * jaroslav@1890: *

The execution status of tasks may be queried at several levels jaroslav@1890: * of detail: {@link #isDone} is true if a task completed in any way jaroslav@1890: * (including the case where a task was cancelled without executing); jaroslav@1890: * {@link #isCompletedNormally} is true if a task completed without jaroslav@1890: * cancellation or encountering an exception; {@link #isCancelled} is jaroslav@1890: * true if the task was cancelled (in which case {@link #getException} jaroslav@1890: * returns a {@link java.util.concurrent.CancellationException}); and jaroslav@1890: * {@link #isCompletedAbnormally} is true if a task was either jaroslav@1890: * cancelled or encountered an exception, in which case {@link jaroslav@1890: * #getException} will return either the encountered exception or jaroslav@1890: * {@link java.util.concurrent.CancellationException}. jaroslav@1890: * jaroslav@1890: *

The ForkJoinTask class is not usually directly subclassed. jaroslav@1890: * Instead, you subclass one of the abstract classes that support a jaroslav@1890: * particular style of fork/join processing, typically {@link jaroslav@1890: * RecursiveAction} for computations that do not return results, or jaroslav@1890: * {@link RecursiveTask} for those that do. Normally, a concrete jaroslav@1890: * ForkJoinTask subclass declares fields comprising its parameters, jaroslav@1890: * established in a constructor, and then defines a {@code compute} jaroslav@1890: * method that somehow uses the control methods supplied by this base jaroslav@1890: * class. While these methods have {@code public} access (to allow jaroslav@1890: * instances of different task subclasses to call each other's jaroslav@1890: * methods), some of them may only be called from within other jaroslav@1890: * ForkJoinTasks (as may be determined using method {@link jaroslav@1890: * #inForkJoinPool}). Attempts to invoke them in other contexts jaroslav@1890: * result in exceptions or errors, possibly including jaroslav@1890: * {@code ClassCastException}. jaroslav@1890: * jaroslav@1890: *

Method {@link #join} and its variants are appropriate for use jaroslav@1890: * only when completion dependencies are acyclic; that is, the jaroslav@1890: * parallel computation can be described as a directed acyclic graph jaroslav@1890: * (DAG). Otherwise, executions may encounter a form of deadlock as jaroslav@1890: * tasks cyclically wait for each other. However, this framework jaroslav@1890: * supports other methods and techniques (for example the use of jaroslav@1890: * {@link Phaser}, {@link #helpQuiesce}, and {@link #complete}) that jaroslav@1890: * may be of use in constructing custom subclasses for problems that jaroslav@1890: * are not statically structured as DAGs. jaroslav@1890: * jaroslav@1890: *

Most base support methods are {@code final}, to prevent jaroslav@1890: * overriding of implementations that are intrinsically tied to the jaroslav@1890: * underlying lightweight task scheduling framework. Developers jaroslav@1890: * creating new basic styles of fork/join processing should minimally jaroslav@1890: * implement {@code protected} methods {@link #exec}, {@link jaroslav@1890: * #setRawResult}, and {@link #getRawResult}, while also introducing jaroslav@1890: * an abstract computational method that can be implemented in its jaroslav@1890: * subclasses, possibly relying on other {@code protected} methods jaroslav@1890: * provided by this class. jaroslav@1890: * jaroslav@1890: *

ForkJoinTasks should perform relatively small amounts of jaroslav@1890: * computation. Large tasks should be split into smaller subtasks, jaroslav@1890: * usually via recursive decomposition. As a very rough rule of thumb, jaroslav@1890: * a task should perform more than 100 and less than 10000 basic jaroslav@1890: * computational steps, and should avoid indefinite looping. If tasks jaroslav@1890: * are too big, then parallelism cannot improve throughput. If too jaroslav@1890: * small, then memory and internal task maintenance overhead may jaroslav@1890: * overwhelm processing. jaroslav@1890: * jaroslav@1890: *

This class provides {@code adapt} methods for {@link Runnable} jaroslav@1890: * and {@link Callable}, that may be of use when mixing execution of jaroslav@1890: * {@code ForkJoinTasks} with other kinds of tasks. When all tasks are jaroslav@1890: * of this form, consider using a pool constructed in asyncMode. jaroslav@1890: * jaroslav@1890: *

ForkJoinTasks are {@code Serializable}, which enables them to be jaroslav@1890: * used in extensions such as remote execution frameworks. It is jaroslav@1890: * sensible to serialize tasks only before or after, but not during, jaroslav@1890: * execution. Serialization is not relied on during execution itself. jaroslav@1890: * jaroslav@1890: * @since 1.7 jaroslav@1890: * @author Doug Lea jaroslav@1890: */ jaroslav@1890: public abstract class ForkJoinTask implements Future, Serializable { jaroslav@1890: jaroslav@1890: /* jaroslav@1890: * See the internal documentation of class ForkJoinPool for a jaroslav@1890: * general implementation overview. ForkJoinTasks are mainly jaroslav@1890: * responsible for maintaining their "status" field amidst relays jaroslav@1890: * to methods in ForkJoinWorkerThread and ForkJoinPool. The jaroslav@1890: * methods of this class are more-or-less layered into (1) basic jaroslav@1890: * status maintenance (2) execution and awaiting completion (3) jaroslav@1890: * user-level methods that additionally report results. This is jaroslav@1890: * sometimes hard to see because this file orders exported methods jaroslav@1890: * in a way that flows well in javadocs. jaroslav@1890: */ jaroslav@1890: jaroslav@1890: /* jaroslav@1890: * The status field holds run control status bits packed into a jaroslav@1890: * single int to minimize footprint and to ensure atomicity (via jaroslav@1890: * CAS). Status is initially zero, and takes on nonnegative jaroslav@1890: * values until completed, upon which status holds value jaroslav@1890: * NORMAL, CANCELLED, or EXCEPTIONAL. Tasks undergoing blocking jaroslav@1890: * waits by other threads have the SIGNAL bit set. Completion of jaroslav@1890: * a stolen task with SIGNAL set awakens any waiters via jaroslav@1890: * notifyAll. Even though suboptimal for some purposes, we use jaroslav@1890: * basic builtin wait/notify to take advantage of "monitor jaroslav@1890: * inflation" in JVMs that we would otherwise need to emulate to jaroslav@1890: * avoid adding further per-task bookkeeping overhead. We want jaroslav@1890: * these monitors to be "fat", i.e., not use biasing or thin-lock jaroslav@1890: * techniques, so use some odd coding idioms that tend to avoid jaroslav@1890: * them. jaroslav@1890: */ jaroslav@1890: jaroslav@1890: /** The run status of this task */ jaroslav@1890: volatile int status; // accessed directly by pool and workers jaroslav@1890: private static final int NORMAL = -1; jaroslav@1890: private static final int CANCELLED = -2; jaroslav@1890: private static final int EXCEPTIONAL = -3; jaroslav@1890: private static final int SIGNAL = 1; jaroslav@1890: jaroslav@1890: /** jaroslav@1890: * Marks completion and wakes up threads waiting to join this task, jaroslav@1890: * also clearing signal request bits. jaroslav@1890: * jaroslav@1890: * @param completion one of NORMAL, CANCELLED, EXCEPTIONAL jaroslav@1890: * @return completion status on exit jaroslav@1890: */ jaroslav@1890: private int setCompletion(int completion) { jaroslav@1890: for (int s;;) { jaroslav@1890: if ((s = status) < 0) jaroslav@1890: return s; jaroslav@1890: if (UNSAFE.compareAndSwapInt(this, statusOffset, s, completion)) { jaroslav@1890: if (s != 0) jaroslav@1890: synchronized (this) { notifyAll(); } jaroslav@1890: return completion; jaroslav@1890: } jaroslav@1890: } jaroslav@1890: } jaroslav@1890: jaroslav@1890: /** jaroslav@1890: * Tries to block a worker thread until completed or timed out. jaroslav@1890: * Uses Object.wait time argument conventions. jaroslav@1890: * May fail on contention or interrupt. jaroslav@1890: * jaroslav@1890: * @param millis if > 0, wait time. jaroslav@1890: */ jaroslav@1890: final void tryAwaitDone(long millis) { jaroslav@1890: int s; jaroslav@1890: try { jaroslav@1890: if (((s = status) > 0 || jaroslav@1890: (s == 0 && jaroslav@1890: UNSAFE.compareAndSwapInt(this, statusOffset, 0, SIGNAL))) && jaroslav@1890: status > 0) { jaroslav@1890: synchronized (this) { jaroslav@1890: if (status > 0) jaroslav@1890: wait(millis); jaroslav@1890: } jaroslav@1890: } jaroslav@1890: } catch (InterruptedException ie) { jaroslav@1890: // caller must check termination jaroslav@1890: } jaroslav@1890: } jaroslav@1890: jaroslav@1890: /** jaroslav@1890: * Blocks a non-worker-thread until completion. jaroslav@1890: * @return status upon completion jaroslav@1890: */ jaroslav@1890: private int externalAwaitDone() { jaroslav@1890: int s; jaroslav@1890: if ((s = status) >= 0) { jaroslav@1890: boolean interrupted = false; jaroslav@1890: synchronized (this) { jaroslav@1890: while ((s = status) >= 0) { jaroslav@1890: if (s == 0) jaroslav@1890: UNSAFE.compareAndSwapInt(this, statusOffset, jaroslav@1890: 0, SIGNAL); jaroslav@1890: else { jaroslav@1890: try { jaroslav@1890: wait(); jaroslav@1890: } catch (InterruptedException ie) { jaroslav@1890: interrupted = true; jaroslav@1890: } jaroslav@1890: } jaroslav@1890: } jaroslav@1890: } jaroslav@1890: if (interrupted) jaroslav@1890: Thread.currentThread().interrupt(); jaroslav@1890: } jaroslav@1890: return s; jaroslav@1890: } jaroslav@1890: jaroslav@1890: /** jaroslav@1890: * Blocks a non-worker-thread until completion or interruption or timeout. jaroslav@1890: */ jaroslav@1890: private int externalInterruptibleAwaitDone(long millis) jaroslav@1890: throws InterruptedException { jaroslav@1890: int s; jaroslav@1890: if (Thread.interrupted()) jaroslav@1890: throw new InterruptedException(); jaroslav@1890: if ((s = status) >= 0) { jaroslav@1890: synchronized (this) { jaroslav@1890: while ((s = status) >= 0) { jaroslav@1890: if (s == 0) jaroslav@1890: UNSAFE.compareAndSwapInt(this, statusOffset, jaroslav@1890: 0, SIGNAL); jaroslav@1890: else { jaroslav@1890: wait(millis); jaroslav@1890: if (millis > 0L) jaroslav@1890: break; jaroslav@1890: } jaroslav@1890: } jaroslav@1890: } jaroslav@1890: } jaroslav@1890: return s; jaroslav@1890: } jaroslav@1890: jaroslav@1890: /** jaroslav@1890: * Primary execution method for stolen tasks. Unless done, calls jaroslav@1890: * exec and records status if completed, but doesn't wait for jaroslav@1890: * completion otherwise. jaroslav@1890: */ jaroslav@1890: final void doExec() { jaroslav@1890: if (status >= 0) { jaroslav@1890: boolean completed; jaroslav@1890: try { jaroslav@1890: completed = exec(); jaroslav@1890: } catch (Throwable rex) { jaroslav@1890: setExceptionalCompletion(rex); jaroslav@1890: return; jaroslav@1890: } jaroslav@1890: if (completed) jaroslav@1890: setCompletion(NORMAL); // must be outside try block jaroslav@1890: } jaroslav@1890: } jaroslav@1890: jaroslav@1890: /** jaroslav@1890: * Primary mechanics for join, get, quietlyJoin. jaroslav@1890: * @return status upon completion jaroslav@1890: */ jaroslav@1890: private int doJoin() { jaroslav@1890: Thread t; ForkJoinWorkerThread w; int s; boolean completed; jaroslav@1890: if ((t = Thread.currentThread()) instanceof ForkJoinWorkerThread) { jaroslav@1890: if ((s = status) < 0) jaroslav@1890: return s; jaroslav@1890: if ((w = (ForkJoinWorkerThread)t).unpushTask(this)) { jaroslav@1890: try { jaroslav@1890: completed = exec(); jaroslav@1890: } catch (Throwable rex) { jaroslav@1890: return setExceptionalCompletion(rex); jaroslav@1890: } jaroslav@1890: if (completed) jaroslav@1890: return setCompletion(NORMAL); jaroslav@1890: } jaroslav@1890: return w.joinTask(this); jaroslav@1890: } jaroslav@1890: else jaroslav@1890: return externalAwaitDone(); jaroslav@1890: } jaroslav@1890: jaroslav@1890: /** jaroslav@1890: * Primary mechanics for invoke, quietlyInvoke. jaroslav@1890: * @return status upon completion jaroslav@1890: */ jaroslav@1890: private int doInvoke() { jaroslav@1890: int s; boolean completed; jaroslav@1890: if ((s = status) < 0) jaroslav@1890: return s; jaroslav@1890: try { jaroslav@1890: completed = exec(); jaroslav@1890: } catch (Throwable rex) { jaroslav@1890: return setExceptionalCompletion(rex); jaroslav@1890: } jaroslav@1890: if (completed) jaroslav@1890: return setCompletion(NORMAL); jaroslav@1890: else jaroslav@1890: return doJoin(); jaroslav@1890: } jaroslav@1890: jaroslav@1890: // Exception table support jaroslav@1890: jaroslav@1890: /** jaroslav@1890: * Table of exceptions thrown by tasks, to enable reporting by jaroslav@1890: * callers. Because exceptions are rare, we don't directly keep jaroslav@1890: * them with task objects, but instead use a weak ref table. Note jaroslav@1890: * that cancellation exceptions don't appear in the table, but are jaroslav@1890: * instead recorded as status values. jaroslav@1890: * jaroslav@1890: * Note: These statics are initialized below in static block. jaroslav@1890: */ jaroslav@1890: private static final ExceptionNode[] exceptionTable; jaroslav@1890: private static final ReentrantLock exceptionTableLock; jaroslav@1890: private static final ReferenceQueue exceptionTableRefQueue; jaroslav@1890: jaroslav@1890: /** jaroslav@1890: * Fixed capacity for exceptionTable. jaroslav@1890: */ jaroslav@1890: private static final int EXCEPTION_MAP_CAPACITY = 32; jaroslav@1890: jaroslav@1890: /** jaroslav@1890: * Key-value nodes for exception table. The chained hash table jaroslav@1890: * uses identity comparisons, full locking, and weak references jaroslav@1890: * for keys. The table has a fixed capacity because it only jaroslav@1890: * maintains task exceptions long enough for joiners to access jaroslav@1890: * them, so should never become very large for sustained jaroslav@1890: * periods. However, since we do not know when the last joiner jaroslav@1890: * completes, we must use weak references and expunge them. We do jaroslav@1890: * so on each operation (hence full locking). Also, some thread in jaroslav@1890: * any ForkJoinPool will call helpExpungeStaleExceptions when its jaroslav@1890: * pool becomes isQuiescent. jaroslav@1890: */ jaroslav@1890: static final class ExceptionNode extends WeakReference>{ jaroslav@1890: final Throwable ex; jaroslav@1890: ExceptionNode next; jaroslav@1890: final long thrower; // use id not ref to avoid weak cycles jaroslav@1890: ExceptionNode(ForkJoinTask task, Throwable ex, ExceptionNode next) { jaroslav@1890: super(task, exceptionTableRefQueue); jaroslav@1890: this.ex = ex; jaroslav@1890: this.next = next; jaroslav@1890: this.thrower = Thread.currentThread().getId(); jaroslav@1890: } jaroslav@1890: } jaroslav@1890: jaroslav@1890: /** jaroslav@1890: * Records exception and sets exceptional completion. jaroslav@1890: * jaroslav@1890: * @return status on exit jaroslav@1890: */ jaroslav@1890: private int setExceptionalCompletion(Throwable ex) { jaroslav@1890: int h = System.identityHashCode(this); jaroslav@1890: final ReentrantLock lock = exceptionTableLock; jaroslav@1890: lock.lock(); jaroslav@1890: try { jaroslav@1890: expungeStaleExceptions(); jaroslav@1890: ExceptionNode[] t = exceptionTable; jaroslav@1890: int i = h & (t.length - 1); jaroslav@1890: for (ExceptionNode e = t[i]; ; e = e.next) { jaroslav@1890: if (e == null) { jaroslav@1890: t[i] = new ExceptionNode(this, ex, t[i]); jaroslav@1890: break; jaroslav@1890: } jaroslav@1890: if (e.get() == this) // already present jaroslav@1890: break; jaroslav@1890: } jaroslav@1890: } finally { jaroslav@1890: lock.unlock(); jaroslav@1890: } jaroslav@1890: return setCompletion(EXCEPTIONAL); jaroslav@1890: } jaroslav@1890: jaroslav@1890: /** jaroslav@1890: * Removes exception node and clears status jaroslav@1890: */ jaroslav@1890: private void clearExceptionalCompletion() { jaroslav@1890: int h = System.identityHashCode(this); jaroslav@1890: final ReentrantLock lock = exceptionTableLock; jaroslav@1890: lock.lock(); jaroslav@1890: try { jaroslav@1890: ExceptionNode[] t = exceptionTable; jaroslav@1890: int i = h & (t.length - 1); jaroslav@1890: ExceptionNode e = t[i]; jaroslav@1890: ExceptionNode pred = null; jaroslav@1890: while (e != null) { jaroslav@1890: ExceptionNode next = e.next; jaroslav@1890: if (e.get() == this) { jaroslav@1890: if (pred == null) jaroslav@1890: t[i] = next; jaroslav@1890: else jaroslav@1890: pred.next = next; jaroslav@1890: break; jaroslav@1890: } jaroslav@1890: pred = e; jaroslav@1890: e = next; jaroslav@1890: } jaroslav@1890: expungeStaleExceptions(); jaroslav@1890: status = 0; jaroslav@1890: } finally { jaroslav@1890: lock.unlock(); jaroslav@1890: } jaroslav@1890: } jaroslav@1890: jaroslav@1890: /** jaroslav@1890: * Returns a rethrowable exception for the given task, if jaroslav@1890: * available. To provide accurate stack traces, if the exception jaroslav@1890: * was not thrown by the current thread, we try to create a new jaroslav@1890: * exception of the same type as the one thrown, but with the jaroslav@1890: * recorded exception as its cause. If there is no such jaroslav@1890: * constructor, we instead try to use a no-arg constructor, jaroslav@1890: * followed by initCause, to the same effect. If none of these jaroslav@1890: * apply, or any fail due to other exceptions, we return the jaroslav@1890: * recorded exception, which is still correct, although it may jaroslav@1890: * contain a misleading stack trace. jaroslav@1890: * jaroslav@1890: * @return the exception, or null if none jaroslav@1890: */ jaroslav@1890: private Throwable getThrowableException() { jaroslav@1890: if (status != EXCEPTIONAL) jaroslav@1890: return null; jaroslav@1890: int h = System.identityHashCode(this); jaroslav@1890: ExceptionNode e; jaroslav@1890: final ReentrantLock lock = exceptionTableLock; jaroslav@1890: lock.lock(); jaroslav@1890: try { jaroslav@1890: expungeStaleExceptions(); jaroslav@1890: ExceptionNode[] t = exceptionTable; jaroslav@1890: e = t[h & (t.length - 1)]; jaroslav@1890: while (e != null && e.get() != this) jaroslav@1890: e = e.next; jaroslav@1890: } finally { jaroslav@1890: lock.unlock(); jaroslav@1890: } jaroslav@1890: Throwable ex; jaroslav@1890: if (e == null || (ex = e.ex) == null) jaroslav@1890: return null; jaroslav@1890: if (e.thrower != Thread.currentThread().getId()) { jaroslav@1890: Class ec = ex.getClass(); jaroslav@1890: try { jaroslav@1890: Constructor noArgCtor = null; jaroslav@1890: Constructor[] cs = ec.getConstructors();// public ctors only jaroslav@1890: for (int i = 0; i < cs.length; ++i) { jaroslav@1890: Constructor c = cs[i]; jaroslav@1890: Class[] ps = c.getParameterTypes(); jaroslav@1890: if (ps.length == 0) jaroslav@1890: noArgCtor = c; jaroslav@1890: else if (ps.length == 1 && ps[0] == Throwable.class) jaroslav@1890: return (Throwable)(c.newInstance(ex)); jaroslav@1890: } jaroslav@1890: if (noArgCtor != null) { jaroslav@1890: Throwable wx = (Throwable)(noArgCtor.newInstance()); jaroslav@1890: wx.initCause(ex); jaroslav@1890: return wx; jaroslav@1890: } jaroslav@1890: } catch (Exception ignore) { jaroslav@1890: } jaroslav@1890: } jaroslav@1890: return ex; jaroslav@1890: } jaroslav@1890: jaroslav@1890: /** jaroslav@1890: * Poll stale refs and remove them. Call only while holding lock. jaroslav@1890: */ jaroslav@1890: private static void expungeStaleExceptions() { jaroslav@1890: for (Object x; (x = exceptionTableRefQueue.poll()) != null;) { jaroslav@1890: if (x instanceof ExceptionNode) { jaroslav@1890: ForkJoinTask key = ((ExceptionNode)x).get(); jaroslav@1890: ExceptionNode[] t = exceptionTable; jaroslav@1890: int i = System.identityHashCode(key) & (t.length - 1); jaroslav@1890: ExceptionNode e = t[i]; jaroslav@1890: ExceptionNode pred = null; jaroslav@1890: while (e != null) { jaroslav@1890: ExceptionNode next = e.next; jaroslav@1890: if (e == x) { jaroslav@1890: if (pred == null) jaroslav@1890: t[i] = next; jaroslav@1890: else jaroslav@1890: pred.next = next; jaroslav@1890: break; jaroslav@1890: } jaroslav@1890: pred = e; jaroslav@1890: e = next; jaroslav@1890: } jaroslav@1890: } jaroslav@1890: } jaroslav@1890: } jaroslav@1890: jaroslav@1890: /** jaroslav@1890: * If lock is available, poll stale refs and remove them. jaroslav@1890: * Called from ForkJoinPool when pools become quiescent. jaroslav@1890: */ jaroslav@1890: static final void helpExpungeStaleExceptions() { jaroslav@1890: final ReentrantLock lock = exceptionTableLock; jaroslav@1890: if (lock.tryLock()) { jaroslav@1890: try { jaroslav@1890: expungeStaleExceptions(); jaroslav@1890: } finally { jaroslav@1890: lock.unlock(); jaroslav@1890: } jaroslav@1890: } jaroslav@1890: } jaroslav@1890: jaroslav@1890: /** jaroslav@1890: * Report the result of invoke or join; called only upon jaroslav@1890: * non-normal return of internal versions. jaroslav@1890: */ jaroslav@1890: private V reportResult() { jaroslav@1890: int s; Throwable ex; jaroslav@1890: if ((s = status) == CANCELLED) jaroslav@1890: throw new CancellationException(); jaroslav@1890: if (s == EXCEPTIONAL && (ex = getThrowableException()) != null) jaroslav@1890: UNSAFE.throwException(ex); jaroslav@1890: return getRawResult(); jaroslav@1890: } jaroslav@1890: jaroslav@1890: // public methods jaroslav@1890: jaroslav@1890: /** jaroslav@1890: * Arranges to asynchronously execute this task. While it is not jaroslav@1890: * necessarily enforced, it is a usage error to fork a task more jaroslav@1890: * than once unless it has completed and been reinitialized. jaroslav@1890: * Subsequent modifications to the state of this task or any data jaroslav@1890: * it operates on are not necessarily consistently observable by jaroslav@1890: * any thread other than the one executing it unless preceded by a jaroslav@1890: * call to {@link #join} or related methods, or a call to {@link jaroslav@1890: * #isDone} returning {@code true}. jaroslav@1890: * jaroslav@1890: *

This method may be invoked only from within {@code jaroslav@1890: * ForkJoinPool} computations (as may be determined using method jaroslav@1890: * {@link #inForkJoinPool}). Attempts to invoke in other contexts jaroslav@1890: * result in exceptions or errors, possibly including {@code jaroslav@1890: * ClassCastException}. jaroslav@1890: * jaroslav@1890: * @return {@code this}, to simplify usage jaroslav@1890: */ jaroslav@1890: public final ForkJoinTask fork() { jaroslav@1890: ((ForkJoinWorkerThread) Thread.currentThread()) jaroslav@1890: .pushTask(this); jaroslav@1890: return this; jaroslav@1890: } jaroslav@1890: jaroslav@1890: /** jaroslav@1890: * Returns the result of the computation when it {@link #isDone is jaroslav@1890: * done}. This method differs from {@link #get()} in that jaroslav@1890: * abnormal completion results in {@code RuntimeException} or jaroslav@1890: * {@code Error}, not {@code ExecutionException}, and that jaroslav@1890: * interrupts of the calling thread do not cause the jaroslav@1890: * method to abruptly return by throwing {@code jaroslav@1890: * InterruptedException}. jaroslav@1890: * jaroslav@1890: * @return the computed result jaroslav@1890: */ jaroslav@1890: public final V join() { jaroslav@1890: if (doJoin() != NORMAL) jaroslav@1890: return reportResult(); jaroslav@1890: else jaroslav@1890: return getRawResult(); jaroslav@1890: } jaroslav@1890: jaroslav@1890: /** jaroslav@1890: * Commences performing this task, awaits its completion if jaroslav@1890: * necessary, and returns its result, or throws an (unchecked) jaroslav@1890: * {@code RuntimeException} or {@code Error} if the underlying jaroslav@1890: * computation did so. jaroslav@1890: * jaroslav@1890: * @return the computed result jaroslav@1890: */ jaroslav@1890: public final V invoke() { jaroslav@1890: if (doInvoke() != NORMAL) jaroslav@1890: return reportResult(); jaroslav@1890: else jaroslav@1890: return getRawResult(); jaroslav@1890: } jaroslav@1890: jaroslav@1890: /** jaroslav@1890: * Forks the given tasks, returning when {@code isDone} holds for jaroslav@1890: * each task or an (unchecked) exception is encountered, in which jaroslav@1890: * case the exception is rethrown. If more than one task jaroslav@1890: * encounters an exception, then this method throws any one of jaroslav@1890: * these exceptions. If any task encounters an exception, the jaroslav@1890: * other may be cancelled. However, the execution status of jaroslav@1890: * individual tasks is not guaranteed upon exceptional return. The jaroslav@1890: * status of each task may be obtained using {@link jaroslav@1890: * #getException()} and related methods to check if they have been jaroslav@1890: * cancelled, completed normally or exceptionally, or left jaroslav@1890: * unprocessed. jaroslav@1890: * jaroslav@1890: *

This method may be invoked only from within {@code jaroslav@1890: * ForkJoinPool} computations (as may be determined using method jaroslav@1890: * {@link #inForkJoinPool}). Attempts to invoke in other contexts jaroslav@1890: * result in exceptions or errors, possibly including {@code jaroslav@1890: * ClassCastException}. jaroslav@1890: * jaroslav@1890: * @param t1 the first task jaroslav@1890: * @param t2 the second task jaroslav@1890: * @throws NullPointerException if any task is null jaroslav@1890: */ jaroslav@1890: public static void invokeAll(ForkJoinTask t1, ForkJoinTask t2) { jaroslav@1890: t2.fork(); jaroslav@1890: t1.invoke(); jaroslav@1890: t2.join(); jaroslav@1890: } jaroslav@1890: jaroslav@1890: /** jaroslav@1890: * Forks the given tasks, returning when {@code isDone} holds for jaroslav@1890: * each task or an (unchecked) exception is encountered, in which jaroslav@1890: * case the exception is rethrown. If more than one task jaroslav@1890: * encounters an exception, then this method throws any one of jaroslav@1890: * these exceptions. If any task encounters an exception, others jaroslav@1890: * may be cancelled. However, the execution status of individual jaroslav@1890: * tasks is not guaranteed upon exceptional return. The status of jaroslav@1890: * each task may be obtained using {@link #getException()} and jaroslav@1890: * related methods to check if they have been cancelled, completed jaroslav@1890: * normally or exceptionally, or left unprocessed. jaroslav@1890: * jaroslav@1890: *

This method may be invoked only from within {@code jaroslav@1890: * ForkJoinPool} computations (as may be determined using method jaroslav@1890: * {@link #inForkJoinPool}). Attempts to invoke in other contexts jaroslav@1890: * result in exceptions or errors, possibly including {@code jaroslav@1890: * ClassCastException}. jaroslav@1890: * jaroslav@1890: * @param tasks the tasks jaroslav@1890: * @throws NullPointerException if any task is null jaroslav@1890: */ jaroslav@1890: public static void invokeAll(ForkJoinTask... tasks) { jaroslav@1890: Throwable ex = null; jaroslav@1890: int last = tasks.length - 1; jaroslav@1890: for (int i = last; i >= 0; --i) { jaroslav@1890: ForkJoinTask t = tasks[i]; jaroslav@1890: if (t == null) { jaroslav@1890: if (ex == null) jaroslav@1890: ex = new NullPointerException(); jaroslav@1890: } jaroslav@1890: else if (i != 0) jaroslav@1890: t.fork(); jaroslav@1890: else if (t.doInvoke() < NORMAL && ex == null) jaroslav@1890: ex = t.getException(); jaroslav@1890: } jaroslav@1890: for (int i = 1; i <= last; ++i) { jaroslav@1890: ForkJoinTask t = tasks[i]; jaroslav@1890: if (t != null) { jaroslav@1890: if (ex != null) jaroslav@1890: t.cancel(false); jaroslav@1890: else if (t.doJoin() < NORMAL && ex == null) jaroslav@1890: ex = t.getException(); jaroslav@1890: } jaroslav@1890: } jaroslav@1890: if (ex != null) jaroslav@1890: UNSAFE.throwException(ex); jaroslav@1890: } jaroslav@1890: jaroslav@1890: /** jaroslav@1890: * Forks all tasks in the specified collection, returning when jaroslav@1890: * {@code isDone} holds for each task or an (unchecked) exception jaroslav@1890: * is encountered, in which case the exception is rethrown. If jaroslav@1890: * more than one task encounters an exception, then this method jaroslav@1890: * throws any one of these exceptions. If any task encounters an jaroslav@1890: * exception, others may be cancelled. However, the execution jaroslav@1890: * status of individual tasks is not guaranteed upon exceptional jaroslav@1890: * return. The status of each task may be obtained using {@link jaroslav@1890: * #getException()} and related methods to check if they have been jaroslav@1890: * cancelled, completed normally or exceptionally, or left jaroslav@1890: * unprocessed. jaroslav@1890: * jaroslav@1890: *

This method may be invoked only from within {@code jaroslav@1890: * ForkJoinPool} computations (as may be determined using method jaroslav@1890: * {@link #inForkJoinPool}). Attempts to invoke in other contexts jaroslav@1890: * result in exceptions or errors, possibly including {@code jaroslav@1890: * ClassCastException}. jaroslav@1890: * jaroslav@1890: * @param tasks the collection of tasks jaroslav@1890: * @return the tasks argument, to simplify usage jaroslav@1890: * @throws NullPointerException if tasks or any element are null jaroslav@1890: */ jaroslav@1890: public static > Collection invokeAll(Collection tasks) { jaroslav@1890: if (!(tasks instanceof RandomAccess) || !(tasks instanceof List)) { jaroslav@1890: invokeAll(tasks.toArray(new ForkJoinTask[tasks.size()])); jaroslav@1890: return tasks; jaroslav@1890: } jaroslav@1890: @SuppressWarnings("unchecked") jaroslav@1890: List> ts = jaroslav@1890: (List>) tasks; jaroslav@1890: Throwable ex = null; jaroslav@1890: int last = ts.size() - 1; jaroslav@1890: for (int i = last; i >= 0; --i) { jaroslav@1890: ForkJoinTask t = ts.get(i); jaroslav@1890: if (t == null) { jaroslav@1890: if (ex == null) jaroslav@1890: ex = new NullPointerException(); jaroslav@1890: } jaroslav@1890: else if (i != 0) jaroslav@1890: t.fork(); jaroslav@1890: else if (t.doInvoke() < NORMAL && ex == null) jaroslav@1890: ex = t.getException(); jaroslav@1890: } jaroslav@1890: for (int i = 1; i <= last; ++i) { jaroslav@1890: ForkJoinTask t = ts.get(i); jaroslav@1890: if (t != null) { jaroslav@1890: if (ex != null) jaroslav@1890: t.cancel(false); jaroslav@1890: else if (t.doJoin() < NORMAL && ex == null) jaroslav@1890: ex = t.getException(); jaroslav@1890: } jaroslav@1890: } jaroslav@1890: if (ex != null) jaroslav@1890: UNSAFE.throwException(ex); jaroslav@1890: return tasks; jaroslav@1890: } jaroslav@1890: jaroslav@1890: /** jaroslav@1890: * Attempts to cancel execution of this task. This attempt will jaroslav@1890: * fail if the task has already completed or could not be jaroslav@1890: * cancelled for some other reason. If successful, and this task jaroslav@1890: * has not started when {@code cancel} is called, execution of jaroslav@1890: * this task is suppressed. After this method returns jaroslav@1890: * successfully, unless there is an intervening call to {@link jaroslav@1890: * #reinitialize}, subsequent calls to {@link #isCancelled}, jaroslav@1890: * {@link #isDone}, and {@code cancel} will return {@code true} jaroslav@1890: * and calls to {@link #join} and related methods will result in jaroslav@1890: * {@code CancellationException}. jaroslav@1890: * jaroslav@1890: *

This method may be overridden in subclasses, but if so, must jaroslav@1890: * still ensure that these properties hold. In particular, the jaroslav@1890: * {@code cancel} method itself must not throw exceptions. jaroslav@1890: * jaroslav@1890: *

This method is designed to be invoked by other jaroslav@1890: * tasks. To terminate the current task, you can just return or jaroslav@1890: * throw an unchecked exception from its computation method, or jaroslav@1890: * invoke {@link #completeExceptionally}. jaroslav@1890: * jaroslav@1890: * @param mayInterruptIfRunning this value has no effect in the jaroslav@1890: * default implementation because interrupts are not used to jaroslav@1890: * control cancellation. jaroslav@1890: * jaroslav@1890: * @return {@code true} if this task is now cancelled jaroslav@1890: */ jaroslav@1890: public boolean cancel(boolean mayInterruptIfRunning) { jaroslav@1890: return setCompletion(CANCELLED) == CANCELLED; jaroslav@1890: } jaroslav@1890: jaroslav@1890: /** jaroslav@1890: * Cancels, ignoring any exceptions thrown by cancel. Used during jaroslav@1890: * worker and pool shutdown. Cancel is spec'ed not to throw any jaroslav@1890: * exceptions, but if it does anyway, we have no recourse during jaroslav@1890: * shutdown, so guard against this case. jaroslav@1890: */ jaroslav@1890: final void cancelIgnoringExceptions() { jaroslav@1890: try { jaroslav@1890: cancel(false); jaroslav@1890: } catch (Throwable ignore) { jaroslav@1890: } jaroslav@1890: } jaroslav@1890: jaroslav@1890: public final boolean isDone() { jaroslav@1890: return status < 0; jaroslav@1890: } jaroslav@1890: jaroslav@1890: public final boolean isCancelled() { jaroslav@1890: return status == CANCELLED; jaroslav@1890: } jaroslav@1890: jaroslav@1890: /** jaroslav@1890: * Returns {@code true} if this task threw an exception or was cancelled. jaroslav@1890: * jaroslav@1890: * @return {@code true} if this task threw an exception or was cancelled jaroslav@1890: */ jaroslav@1890: public final boolean isCompletedAbnormally() { jaroslav@1890: return status < NORMAL; jaroslav@1890: } jaroslav@1890: jaroslav@1890: /** jaroslav@1890: * Returns {@code true} if this task completed without throwing an jaroslav@1890: * exception and was not cancelled. jaroslav@1890: * jaroslav@1890: * @return {@code true} if this task completed without throwing an jaroslav@1890: * exception and was not cancelled jaroslav@1890: */ jaroslav@1890: public final boolean isCompletedNormally() { jaroslav@1890: return status == NORMAL; jaroslav@1890: } jaroslav@1890: jaroslav@1890: /** jaroslav@1890: * Returns the exception thrown by the base computation, or a jaroslav@1890: * {@code CancellationException} if cancelled, or {@code null} if jaroslav@1890: * none or if the method has not yet completed. jaroslav@1890: * jaroslav@1890: * @return the exception, or {@code null} if none jaroslav@1890: */ jaroslav@1890: public final Throwable getException() { jaroslav@1890: int s = status; jaroslav@1890: return ((s >= NORMAL) ? null : jaroslav@1890: (s == CANCELLED) ? new CancellationException() : jaroslav@1890: getThrowableException()); jaroslav@1890: } jaroslav@1890: jaroslav@1890: /** jaroslav@1890: * Completes this task abnormally, and if not already aborted or jaroslav@1890: * cancelled, causes it to throw the given exception upon jaroslav@1890: * {@code join} and related operations. This method may be used jaroslav@1890: * to induce exceptions in asynchronous tasks, or to force jaroslav@1890: * completion of tasks that would not otherwise complete. Its use jaroslav@1890: * in other situations is discouraged. This method is jaroslav@1890: * overridable, but overridden versions must invoke {@code super} jaroslav@1890: * implementation to maintain guarantees. jaroslav@1890: * jaroslav@1890: * @param ex the exception to throw. If this exception is not a jaroslav@1890: * {@code RuntimeException} or {@code Error}, the actual exception jaroslav@1890: * thrown will be a {@code RuntimeException} with cause {@code ex}. jaroslav@1890: */ jaroslav@1890: public void completeExceptionally(Throwable ex) { jaroslav@1890: setExceptionalCompletion((ex instanceof RuntimeException) || jaroslav@1890: (ex instanceof Error) ? ex : jaroslav@1890: new RuntimeException(ex)); jaroslav@1890: } jaroslav@1890: jaroslav@1890: /** jaroslav@1890: * Completes this task, and if not already aborted or cancelled, jaroslav@1890: * returning the given value as the result of subsequent jaroslav@1890: * invocations of {@code join} and related operations. This method jaroslav@1890: * may be used to provide results for asynchronous tasks, or to jaroslav@1890: * provide alternative handling for tasks that would not otherwise jaroslav@1890: * complete normally. Its use in other situations is jaroslav@1890: * discouraged. This method is overridable, but overridden jaroslav@1890: * versions must invoke {@code super} implementation to maintain jaroslav@1890: * guarantees. jaroslav@1890: * jaroslav@1890: * @param value the result value for this task jaroslav@1890: */ jaroslav@1890: public void complete(V value) { jaroslav@1890: try { jaroslav@1890: setRawResult(value); jaroslav@1890: } catch (Throwable rex) { jaroslav@1890: setExceptionalCompletion(rex); jaroslav@1890: return; jaroslav@1890: } jaroslav@1890: setCompletion(NORMAL); jaroslav@1890: } jaroslav@1890: jaroslav@1890: /** jaroslav@1890: * Waits if necessary for the computation to complete, and then jaroslav@1890: * retrieves its result. jaroslav@1890: * jaroslav@1890: * @return the computed result jaroslav@1890: * @throws CancellationException if the computation was cancelled jaroslav@1890: * @throws ExecutionException if the computation threw an jaroslav@1890: * exception jaroslav@1890: * @throws InterruptedException if the current thread is not a jaroslav@1890: * member of a ForkJoinPool and was interrupted while waiting jaroslav@1890: */ jaroslav@1890: public final V get() throws InterruptedException, ExecutionException { jaroslav@1890: int s = (Thread.currentThread() instanceof ForkJoinWorkerThread) ? jaroslav@1890: doJoin() : externalInterruptibleAwaitDone(0L); jaroslav@1890: Throwable ex; jaroslav@1890: if (s == CANCELLED) jaroslav@1890: throw new CancellationException(); jaroslav@1890: if (s == EXCEPTIONAL && (ex = getThrowableException()) != null) jaroslav@1890: throw new ExecutionException(ex); jaroslav@1890: return getRawResult(); jaroslav@1890: } jaroslav@1890: jaroslav@1890: /** jaroslav@1890: * Waits if necessary for at most the given time for the computation jaroslav@1890: * to complete, and then retrieves its result, if available. jaroslav@1890: * jaroslav@1890: * @param timeout the maximum time to wait jaroslav@1890: * @param unit the time unit of the timeout argument jaroslav@1890: * @return the computed result jaroslav@1890: * @throws CancellationException if the computation was cancelled jaroslav@1890: * @throws ExecutionException if the computation threw an jaroslav@1890: * exception jaroslav@1890: * @throws InterruptedException if the current thread is not a jaroslav@1890: * member of a ForkJoinPool and was interrupted while waiting jaroslav@1890: * @throws TimeoutException if the wait timed out jaroslav@1890: */ jaroslav@1890: public final V get(long timeout, TimeUnit unit) jaroslav@1890: throws InterruptedException, ExecutionException, TimeoutException { jaroslav@1890: Thread t = Thread.currentThread(); jaroslav@1890: if (t instanceof ForkJoinWorkerThread) { jaroslav@1890: ForkJoinWorkerThread w = (ForkJoinWorkerThread) t; jaroslav@1890: long nanos = unit.toNanos(timeout); jaroslav@1890: if (status >= 0) { jaroslav@1890: boolean completed = false; jaroslav@1890: if (w.unpushTask(this)) { jaroslav@1890: try { jaroslav@1890: completed = exec(); jaroslav@1890: } catch (Throwable rex) { jaroslav@1890: setExceptionalCompletion(rex); jaroslav@1890: } jaroslav@1890: } jaroslav@1890: if (completed) jaroslav@1890: setCompletion(NORMAL); jaroslav@1890: else if (status >= 0 && nanos > 0) jaroslav@1890: w.pool.timedAwaitJoin(this, nanos); jaroslav@1890: } jaroslav@1890: } jaroslav@1890: else { jaroslav@1890: long millis = unit.toMillis(timeout); jaroslav@1890: if (millis > 0) jaroslav@1890: externalInterruptibleAwaitDone(millis); jaroslav@1890: } jaroslav@1890: int s = status; jaroslav@1890: if (s != NORMAL) { jaroslav@1890: Throwable ex; jaroslav@1890: if (s == CANCELLED) jaroslav@1890: throw new CancellationException(); jaroslav@1890: if (s != EXCEPTIONAL) jaroslav@1890: throw new TimeoutException(); jaroslav@1890: if ((ex = getThrowableException()) != null) jaroslav@1890: throw new ExecutionException(ex); jaroslav@1890: } jaroslav@1890: return getRawResult(); jaroslav@1890: } jaroslav@1890: jaroslav@1890: /** jaroslav@1890: * Joins this task, without returning its result or throwing its jaroslav@1890: * exception. This method may be useful when processing jaroslav@1890: * collections of tasks when some have been cancelled or otherwise jaroslav@1890: * known to have aborted. jaroslav@1890: */ jaroslav@1890: public final void quietlyJoin() { jaroslav@1890: doJoin(); jaroslav@1890: } jaroslav@1890: jaroslav@1890: /** jaroslav@1890: * Commences performing this task and awaits its completion if jaroslav@1890: * necessary, without returning its result or throwing its jaroslav@1890: * exception. jaroslav@1890: */ jaroslav@1890: public final void quietlyInvoke() { jaroslav@1890: doInvoke(); jaroslav@1890: } jaroslav@1890: jaroslav@1890: /** jaroslav@1890: * Possibly executes tasks until the pool hosting the current task jaroslav@1890: * {@link ForkJoinPool#isQuiescent is quiescent}. This method may jaroslav@1890: * be of use in designs in which many tasks are forked, but none jaroslav@1890: * are explicitly joined, instead executing them until all are jaroslav@1890: * processed. jaroslav@1890: * jaroslav@1890: *

This method may be invoked only from within {@code jaroslav@1890: * ForkJoinPool} computations (as may be determined using method jaroslav@1890: * {@link #inForkJoinPool}). Attempts to invoke in other contexts jaroslav@1890: * result in exceptions or errors, possibly including {@code jaroslav@1890: * ClassCastException}. jaroslav@1890: */ jaroslav@1890: public static void helpQuiesce() { jaroslav@1890: ((ForkJoinWorkerThread) Thread.currentThread()) jaroslav@1890: .helpQuiescePool(); jaroslav@1890: } jaroslav@1890: jaroslav@1890: /** jaroslav@1890: * Resets the internal bookkeeping state of this task, allowing a jaroslav@1890: * subsequent {@code fork}. This method allows repeated reuse of jaroslav@1890: * this task, but only if reuse occurs when this task has either jaroslav@1890: * never been forked, or has been forked, then completed and all jaroslav@1890: * outstanding joins of this task have also completed. Effects jaroslav@1890: * under any other usage conditions are not guaranteed. jaroslav@1890: * This method may be useful when executing jaroslav@1890: * pre-constructed trees of subtasks in loops. jaroslav@1890: * jaroslav@1890: *

Upon completion of this method, {@code isDone()} reports jaroslav@1890: * {@code false}, and {@code getException()} reports {@code jaroslav@1890: * null}. However, the value returned by {@code getRawResult} is jaroslav@1890: * unaffected. To clear this value, you can invoke {@code jaroslav@1890: * setRawResult(null)}. jaroslav@1890: */ jaroslav@1890: public void reinitialize() { jaroslav@1890: if (status == EXCEPTIONAL) jaroslav@1890: clearExceptionalCompletion(); jaroslav@1890: else jaroslav@1890: status = 0; jaroslav@1890: } jaroslav@1890: jaroslav@1890: /** jaroslav@1890: * Returns the pool hosting the current task execution, or null jaroslav@1890: * if this task is executing outside of any ForkJoinPool. jaroslav@1890: * jaroslav@1890: * @see #inForkJoinPool jaroslav@1890: * @return the pool, or {@code null} if none jaroslav@1890: */ jaroslav@1890: public static ForkJoinPool getPool() { jaroslav@1890: Thread t = Thread.currentThread(); jaroslav@1890: return (t instanceof ForkJoinWorkerThread) ? jaroslav@1890: ((ForkJoinWorkerThread) t).pool : null; jaroslav@1890: } jaroslav@1890: jaroslav@1890: /** jaroslav@1890: * Returns {@code true} if the current thread is a {@link jaroslav@1890: * ForkJoinWorkerThread} executing as a ForkJoinPool computation. jaroslav@1890: * jaroslav@1890: * @return {@code true} if the current thread is a {@link jaroslav@1890: * ForkJoinWorkerThread} executing as a ForkJoinPool computation, jaroslav@1890: * or {@code false} otherwise jaroslav@1890: */ jaroslav@1890: public static boolean inForkJoinPool() { jaroslav@1890: return Thread.currentThread() instanceof ForkJoinWorkerThread; jaroslav@1890: } jaroslav@1890: jaroslav@1890: /** jaroslav@1890: * Tries to unschedule this task for execution. This method will jaroslav@1890: * typically succeed if this task is the most recently forked task jaroslav@1890: * by the current thread, and has not commenced executing in jaroslav@1890: * another thread. This method may be useful when arranging jaroslav@1890: * alternative local processing of tasks that could have been, but jaroslav@1890: * were not, stolen. jaroslav@1890: * jaroslav@1890: *

This method may be invoked only from within {@code jaroslav@1890: * ForkJoinPool} computations (as may be determined using method jaroslav@1890: * {@link #inForkJoinPool}). Attempts to invoke in other contexts jaroslav@1890: * result in exceptions or errors, possibly including {@code jaroslav@1890: * ClassCastException}. jaroslav@1890: * jaroslav@1890: * @return {@code true} if unforked jaroslav@1890: */ jaroslav@1890: public boolean tryUnfork() { jaroslav@1890: return ((ForkJoinWorkerThread) Thread.currentThread()) jaroslav@1890: .unpushTask(this); jaroslav@1890: } jaroslav@1890: jaroslav@1890: /** jaroslav@1890: * Returns an estimate of the number of tasks that have been jaroslav@1890: * forked by the current worker thread but not yet executed. This jaroslav@1890: * value may be useful for heuristic decisions about whether to jaroslav@1890: * fork other tasks. jaroslav@1890: * jaroslav@1890: *

This method may be invoked only from within {@code jaroslav@1890: * ForkJoinPool} computations (as may be determined using method jaroslav@1890: * {@link #inForkJoinPool}). Attempts to invoke in other contexts jaroslav@1890: * result in exceptions or errors, possibly including {@code jaroslav@1890: * ClassCastException}. jaroslav@1890: * jaroslav@1890: * @return the number of tasks jaroslav@1890: */ jaroslav@1890: public static int getQueuedTaskCount() { jaroslav@1890: return ((ForkJoinWorkerThread) Thread.currentThread()) jaroslav@1890: .getQueueSize(); jaroslav@1890: } jaroslav@1890: jaroslav@1890: /** jaroslav@1890: * Returns an estimate of how many more locally queued tasks are jaroslav@1890: * held by the current worker thread than there are other worker jaroslav@1890: * threads that might steal them. This value may be useful for jaroslav@1890: * heuristic decisions about whether to fork other tasks. In many jaroslav@1890: * usages of ForkJoinTasks, at steady state, each worker should jaroslav@1890: * aim to maintain a small constant surplus (for example, 3) of jaroslav@1890: * tasks, and to process computations locally if this threshold is jaroslav@1890: * exceeded. jaroslav@1890: * jaroslav@1890: *

This method may be invoked only from within {@code jaroslav@1890: * ForkJoinPool} computations (as may be determined using method jaroslav@1890: * {@link #inForkJoinPool}). Attempts to invoke in other contexts jaroslav@1890: * result in exceptions or errors, possibly including {@code jaroslav@1890: * ClassCastException}. jaroslav@1890: * jaroslav@1890: * @return the surplus number of tasks, which may be negative jaroslav@1890: */ jaroslav@1890: public static int getSurplusQueuedTaskCount() { jaroslav@1890: return ((ForkJoinWorkerThread) Thread.currentThread()) jaroslav@1890: .getEstimatedSurplusTaskCount(); jaroslav@1890: } jaroslav@1890: jaroslav@1890: // Extension methods jaroslav@1890: jaroslav@1890: /** jaroslav@1890: * Returns the result that would be returned by {@link #join}, even jaroslav@1890: * if this task completed abnormally, or {@code null} if this task jaroslav@1890: * is not known to have been completed. This method is designed jaroslav@1890: * to aid debugging, as well as to support extensions. Its use in jaroslav@1890: * any other context is discouraged. jaroslav@1890: * jaroslav@1890: * @return the result, or {@code null} if not completed jaroslav@1890: */ jaroslav@1890: public abstract V getRawResult(); jaroslav@1890: jaroslav@1890: /** jaroslav@1890: * Forces the given value to be returned as a result. This method jaroslav@1890: * is designed to support extensions, and should not in general be jaroslav@1890: * called otherwise. jaroslav@1890: * jaroslav@1890: * @param value the value jaroslav@1890: */ jaroslav@1890: protected abstract void setRawResult(V value); jaroslav@1890: jaroslav@1890: /** jaroslav@1890: * Immediately performs the base action of this task. This method jaroslav@1890: * is designed to support extensions, and should not in general be jaroslav@1890: * called otherwise. The return value controls whether this task jaroslav@1890: * is considered to be done normally. It may return false in jaroslav@1890: * asynchronous actions that require explicit invocations of jaroslav@1890: * {@link #complete} to become joinable. It may also throw an jaroslav@1890: * (unchecked) exception to indicate abnormal exit. jaroslav@1890: * jaroslav@1890: * @return {@code true} if completed normally jaroslav@1890: */ jaroslav@1890: protected abstract boolean exec(); jaroslav@1890: jaroslav@1890: /** jaroslav@1890: * Returns, but does not unschedule or execute, a task queued by jaroslav@1890: * the current thread but not yet executed, if one is immediately jaroslav@1890: * available. There is no guarantee that this task will actually jaroslav@1890: * be polled or executed next. Conversely, this method may return jaroslav@1890: * null even if a task exists but cannot be accessed without jaroslav@1890: * contention with other threads. This method is designed jaroslav@1890: * primarily to support extensions, and is unlikely to be useful jaroslav@1890: * otherwise. jaroslav@1890: * jaroslav@1890: *

This method may be invoked only from within {@code jaroslav@1890: * ForkJoinPool} computations (as may be determined using method jaroslav@1890: * {@link #inForkJoinPool}). Attempts to invoke in other contexts jaroslav@1890: * result in exceptions or errors, possibly including {@code jaroslav@1890: * ClassCastException}. jaroslav@1890: * jaroslav@1890: * @return the next task, or {@code null} if none are available jaroslav@1890: */ jaroslav@1890: protected static ForkJoinTask peekNextLocalTask() { jaroslav@1890: return ((ForkJoinWorkerThread) Thread.currentThread()) jaroslav@1890: .peekTask(); jaroslav@1890: } jaroslav@1890: jaroslav@1890: /** jaroslav@1890: * Unschedules and returns, without executing, the next task jaroslav@1890: * queued by the current thread but not yet executed. This method jaroslav@1890: * is designed primarily to support extensions, and is unlikely to jaroslav@1890: * be useful otherwise. jaroslav@1890: * jaroslav@1890: *

This method may be invoked only from within {@code jaroslav@1890: * ForkJoinPool} computations (as may be determined using method jaroslav@1890: * {@link #inForkJoinPool}). Attempts to invoke in other contexts jaroslav@1890: * result in exceptions or errors, possibly including {@code jaroslav@1890: * ClassCastException}. jaroslav@1890: * jaroslav@1890: * @return the next task, or {@code null} if none are available jaroslav@1890: */ jaroslav@1890: protected static ForkJoinTask pollNextLocalTask() { jaroslav@1890: return ((ForkJoinWorkerThread) Thread.currentThread()) jaroslav@1890: .pollLocalTask(); jaroslav@1890: } jaroslav@1890: jaroslav@1890: /** jaroslav@1890: * Unschedules and returns, without executing, the next task jaroslav@1890: * queued by the current thread but not yet executed, if one is jaroslav@1890: * available, or if not available, a task that was forked by some jaroslav@1890: * other thread, if available. Availability may be transient, so a jaroslav@1890: * {@code null} result does not necessarily imply quiescence jaroslav@1890: * of the pool this task is operating in. This method is designed jaroslav@1890: * primarily to support extensions, and is unlikely to be useful jaroslav@1890: * otherwise. jaroslav@1890: * jaroslav@1890: *

This method may be invoked only from within {@code jaroslav@1890: * ForkJoinPool} computations (as may be determined using method jaroslav@1890: * {@link #inForkJoinPool}). Attempts to invoke in other contexts jaroslav@1890: * result in exceptions or errors, possibly including {@code jaroslav@1890: * ClassCastException}. jaroslav@1890: * jaroslav@1890: * @return a task, or {@code null} if none are available jaroslav@1890: */ jaroslav@1890: protected static ForkJoinTask pollTask() { jaroslav@1890: return ((ForkJoinWorkerThread) Thread.currentThread()) jaroslav@1890: .pollTask(); jaroslav@1890: } jaroslav@1890: jaroslav@1890: /** jaroslav@1890: * Adaptor for Runnables. This implements RunnableFuture jaroslav@1890: * to be compliant with AbstractExecutorService constraints jaroslav@1890: * when used in ForkJoinPool. jaroslav@1890: */ jaroslav@1890: static final class AdaptedRunnable extends ForkJoinTask jaroslav@1890: implements RunnableFuture { jaroslav@1890: final Runnable runnable; jaroslav@1890: final T resultOnCompletion; jaroslav@1890: T result; jaroslav@1890: AdaptedRunnable(Runnable runnable, T result) { jaroslav@1890: if (runnable == null) throw new NullPointerException(); jaroslav@1890: this.runnable = runnable; jaroslav@1890: this.resultOnCompletion = result; jaroslav@1890: } jaroslav@1890: public T getRawResult() { return result; } jaroslav@1890: public void setRawResult(T v) { result = v; } jaroslav@1890: public boolean exec() { jaroslav@1890: runnable.run(); jaroslav@1890: result = resultOnCompletion; jaroslav@1890: return true; jaroslav@1890: } jaroslav@1890: public void run() { invoke(); } jaroslav@1890: private static final long serialVersionUID = 5232453952276885070L; jaroslav@1890: } jaroslav@1890: jaroslav@1890: /** jaroslav@1890: * Adaptor for Callables jaroslav@1890: */ jaroslav@1890: static final class AdaptedCallable extends ForkJoinTask jaroslav@1890: implements RunnableFuture { jaroslav@1890: final Callable callable; jaroslav@1890: T result; jaroslav@1890: AdaptedCallable(Callable callable) { jaroslav@1890: if (callable == null) throw new NullPointerException(); jaroslav@1890: this.callable = callable; jaroslav@1890: } jaroslav@1890: public T getRawResult() { return result; } jaroslav@1890: public void setRawResult(T v) { result = v; } jaroslav@1890: public boolean exec() { jaroslav@1890: try { jaroslav@1890: result = callable.call(); jaroslav@1890: return true; jaroslav@1890: } catch (Error err) { jaroslav@1890: throw err; jaroslav@1890: } catch (RuntimeException rex) { jaroslav@1890: throw rex; jaroslav@1890: } catch (Exception ex) { jaroslav@1890: throw new RuntimeException(ex); jaroslav@1890: } jaroslav@1890: } jaroslav@1890: public void run() { invoke(); } jaroslav@1890: private static final long serialVersionUID = 2838392045355241008L; jaroslav@1890: } jaroslav@1890: jaroslav@1890: /** jaroslav@1890: * Returns a new {@code ForkJoinTask} that performs the {@code run} jaroslav@1890: * method of the given {@code Runnable} as its action, and returns jaroslav@1890: * a null result upon {@link #join}. jaroslav@1890: * jaroslav@1890: * @param runnable the runnable action jaroslav@1890: * @return the task jaroslav@1890: */ jaroslav@1890: public static ForkJoinTask adapt(Runnable runnable) { jaroslav@1890: return new AdaptedRunnable(runnable, null); jaroslav@1890: } jaroslav@1890: jaroslav@1890: /** jaroslav@1890: * Returns a new {@code ForkJoinTask} that performs the {@code run} jaroslav@1890: * method of the given {@code Runnable} as its action, and returns jaroslav@1890: * the given result upon {@link #join}. jaroslav@1890: * jaroslav@1890: * @param runnable the runnable action jaroslav@1890: * @param result the result upon completion jaroslav@1890: * @return the task jaroslav@1890: */ jaroslav@1890: public static ForkJoinTask adapt(Runnable runnable, T result) { jaroslav@1890: return new AdaptedRunnable(runnable, result); jaroslav@1890: } jaroslav@1890: jaroslav@1890: /** jaroslav@1890: * Returns a new {@code ForkJoinTask} that performs the {@code call} jaroslav@1890: * method of the given {@code Callable} as its action, and returns jaroslav@1890: * its result upon {@link #join}, translating any checked exceptions jaroslav@1890: * encountered into {@code RuntimeException}. jaroslav@1890: * jaroslav@1890: * @param callable the callable action jaroslav@1890: * @return the task jaroslav@1890: */ jaroslav@1890: public static ForkJoinTask adapt(Callable callable) { jaroslav@1890: return new AdaptedCallable(callable); jaroslav@1890: } jaroslav@1890: jaroslav@1890: // Serialization support jaroslav@1890: jaroslav@1890: private static final long serialVersionUID = -7721805057305804111L; jaroslav@1890: jaroslav@1890: /** jaroslav@1890: * Saves the state to a stream (that is, serializes it). jaroslav@1890: * jaroslav@1890: * @serialData the current run status and the exception thrown jaroslav@1890: * during execution, or {@code null} if none jaroslav@1890: * @param s the stream jaroslav@1890: */ jaroslav@1890: private void writeObject(java.io.ObjectOutputStream s) jaroslav@1890: throws java.io.IOException { jaroslav@1890: s.defaultWriteObject(); jaroslav@1890: s.writeObject(getException()); jaroslav@1890: } jaroslav@1890: jaroslav@1890: /** jaroslav@1890: * Reconstitutes the instance from a stream (that is, deserializes it). jaroslav@1890: * jaroslav@1890: * @param s the stream jaroslav@1890: */ jaroslav@1890: private void readObject(java.io.ObjectInputStream s) jaroslav@1890: throws java.io.IOException, ClassNotFoundException { jaroslav@1890: s.defaultReadObject(); jaroslav@1890: Object ex = s.readObject(); jaroslav@1890: if (ex != null) jaroslav@1890: setExceptionalCompletion((Throwable)ex); jaroslav@1890: } jaroslav@1890: jaroslav@1890: // Unsafe mechanics jaroslav@1890: private static final sun.misc.Unsafe UNSAFE; jaroslav@1890: private static final long statusOffset; jaroslav@1890: static { jaroslav@1890: exceptionTableLock = new ReentrantLock(); jaroslav@1890: exceptionTableRefQueue = new ReferenceQueue(); jaroslav@1890: exceptionTable = new ExceptionNode[EXCEPTION_MAP_CAPACITY]; jaroslav@1890: try { jaroslav@1890: UNSAFE = sun.misc.Unsafe.getUnsafe(); jaroslav@1890: statusOffset = UNSAFE.objectFieldOffset jaroslav@1890: (ForkJoinTask.class.getDeclaredField("status")); jaroslav@1890: } catch (Exception e) { jaroslav@1890: throw new Error(e); jaroslav@1890: } jaroslav@1890: } jaroslav@1890: jaroslav@1890: }