/* * Written by Doug Lea with assistance from members of JCP JSR-166 * Expert Group and released to the public domain, as explained at * http://creativecommons.org/licenses/publicdomain */ package jsr166y.forkjoin; import jsr166y.*; import java.util.*; import java.util.concurrent.*; import java.util.concurrent.atomic.*; import java.util.concurrent.locks.*; import sun.misc.Unsafe; import java.lang.reflect.*; /** * A thread that is internally managed by a ForkJoinPool to execute * ForkJoinTasks. This class additionally provides public * <tt>static</tt> methods accessing some basic scheduling and * execution mechanics for the <em>current</em> * ForkJoinWorkerThread. These methods may be invoked only from within * other ForkJoinTask computations. Attempts to invoke in other * contexts result in exceptions or errors including * ClassCastException. These methods enable construction of * special-purpose task classes, as well as specialized idioms * occasionally useful in ForkJoinTask processing. * * <p>The form of supported static methods reflects the fact that * worker threads may access and process tasks obtained in any of * three ways. In preference order: <em>Local</em> tasks are processed * in LIFO (newest first) order. <em>Stolen</em> tasks are obtained * from other threads in FIFO (oldest first) order, only if there are * no local tasks to run. <em>Submissions</em> form a FIFO queue * common to the entire pool, and are started only if no other * work is available. * * <p> This class also includes utility methods for accessing and * manipulating submissions to the pool, in support of extensions that * provide more extensive error recovery and/or alternate forms of * execution. * * <p> This class is subclassable solely for the sake of adding * functionality -- there are no overridable methods dealing with * scheduling or execution. However, you can override initialization * and termination cleanup methods surrounding the main task * processing loop. If you do create such a subclass, you will also * need to supply a custom ForkJoinWorkerThreadFactory to use it in a * ForkJoinPool. */ public class ForkJoinWorkerThread extends Thread { /* * Algorithm overview: * * 1. Work-Stealing: Work-stealing queues are special forms of * Deques that support only three of the four possible * end-operations -- push, pop, and deq (aka steal), and only do * so under the constraints that push and pop are called only from * the owning thread, while deq may be called from other threads. * (If you are unfamiliar with them, you probably want to read * Herlihy and Shavit's book "The Art of Multiprocessor * programming", chapter 16 describing these in more detail before * proceeding.) The main work-stealing queue design is roughly * similar to "Dynamic Circular Work-Stealing Deque" by David * Chase and Yossi Lev, SPAA 2005 * (http://research.sun.com/scalable/pubs/index.html). The main * difference ultimately stems from gc requirements that we null * out taken slots as soon as we can, to maintain as small a * footprint as possible even in programs generating huge numbers * of tasks. To accomplish this, we shift the CAS arbitrating pop * vs deq (steal) from being on the indices ("base" and "sp") to * the slots themselves (mainly via method "casSlotNull()"). So, * both a successful pop and deq mainly entail CAS'ing a nonnull * slot to null. Because we rely on CASes of references, we do * not need tag bits on base or sp. They are simple ints as used * in any circular array-based queue (see for example ArrayDeque). * Updates to the indices must still be ordered in a way that * guarantees that (sp - base) > 0 means the queue is empty, but * otherwise may err on the side of possibly making the queue * appear nonempty when a push, pop, or deq have not fully * committed. Note that this means that the deq operation, * considered individually, is not wait-free. One thief cannot * successfully continue until another in-progress one (or, if * previously empty, a push) completes. However, in the * aggregate, we ensure at least probablistic non-blockingness. If * an attempted steal fails, a thief always chooses a different * random victim target to try next. So, in order for one thief to * progress, it suffices for any in-progress deq or new push on * any empty queue to complete. One reason this works well here is * that apparently-nonempty often means soon-to-be-stealable, * which gives threads a chance to activate if necessary before * stealing (see below). * * Efficient implementation of this approach currently relies on * an uncomfortable amount of "Unsafe" mechanics. To maintain * correct orderings, reads and writes of variable base require * volatile ordering. Variable sp does not require volatile loads * (so long as other threads read base first), but require * store-ordering on writes. Because they are protected by * volatile base reads, reads of the queue array and its slots do * not need volatile load semantics, but writes (in push) require * store order and CASes (in pop and deq) require (volatile) CAS * semantics. Since these combinations aren't supported using * ordinary volatiles, the only way to accomplish these effciently * is to use direct Unsafe calls. (Using external AtomicIntegers * and AtomicReferenceArrays for the indices and array is * significantly slower because of memory locality and indirection * effects.) Further, performance on most platforms is very * sensitive to placement and sizing of the (resizable) queue * array. Even though these queues don't usually become all that * big, the initial size must be large enough to counteract cache * contention effects across multiple queues (especially in the * presence of GC cardmarking), Also, to improve thread-locality, * queues are currently initialized immediately after the thread * gets the initial signal to start processing tasks. However, * all queue-related methods except pushTask are written in a way * that allows them to instead be lazily allocated and/or disposed * of when empty. All together, these low-level implementation * choices produce as much as a factor of 4 performance * improvement compared to naive implementations, and enable the * processing of billions of tasks per second, sometimes at the * expense of ugliness. * * 2. Run control: The primary run control is based on a global * counter (activeCount) held by the pool. It uses an algorithm * similar to that in Herlihy and Shavit section 17.6 to cause * threads to eventually block when all threads declare they are * inactive. (See variable "scans".) For this to work, threads * must be declared active when executing tasks, and before * stealing a task. They must be inactive before blocking on the * PoolBarrier (awaiting a new submission or other Pool event). In * between, there is some free play which we take advantage of to * avoid contention and rapid flickering of the global * activeCount: If inactive, we activate only if a victim queue * appears to be nonempty (see above), and even then, back off, * looking for another victim if the attempt (CAS) to increase * activeCount fails. Similarly, a thread tries to inactivate * only after a full scan of other threads, and if the attempted * decrement fails, rescans instead. The net effect is that * contention on activeCount is rarely a measurable performance * issue. (There are also a few other cases where we scan for work * rather than retry/block upon contention.) * * Unlike in previous incarnations of this framework, we do not * ever block worker threads while submissions are executing * (i.e., activeCount is nonzero). Doing so can lead to anomalies * (like convoying of dependent threads) and overheads that negate * benefits. To compensate, we ensure that threads looking for * work are extremely well-behaved. Scans (mainly in * getStolenTask; also getSubmission and scanWhileJoining) do not * modify any variables that might disrupt caches (except, when * necessary, activation status) and probe only the base/sp fields * of other threads unless they appear non-empty. We also * occasionally perform Thread.yields, which may or may not * improve good citizenship. It may be possible to replace this * with a different advisory blocking scheme that better shields * users from the effects of poor ForkJoin task design causing * imbalances, in turn causing excessive spins. * * 3. Selection control. We maintain policy of always choosing to * run local tasks rather than stealing, and always trying to * steal tasks before trying to run a new submission. This shows * up in different ways in different cases though, accounting for * the number of different run/get methods. All steals are * currently performed in randomly-chosen deq-order. It may be * worthwhile to bias these with locality / anti-locality * information, but doing this well probably requires more * lower-level information from JVMs than currently provided. */ /** * Capacity of work-stealing queue array upon initialization. * Must be a power of two. Initial size must be at least 2, but is * padded to minimize cache effects. */ private static final int INITIAL_QUEUE_CAPACITY = 1 << 13; /** * Maximum work-stealing queue array size. Must be less than or * equal to 1 << 30 to ensure lack of index wraparound. */ private static final int MAXIMUM_QUEUE_CAPACITY = 1 << 30; /** * Generator of seeds for per-thread random numbers. */ private static final Random randomSeedGenerator = new Random(); /** * Run state of this worker. */ private final RunState runState; /** * The pool this thread works in. */ private final ForkJoinPool pool; /** * The work-stealing queue array. Size must be a power of two. */ private ForkJoinTask<?>[] queue; /** * Index (mod queue.length) of next queue slot to push to or pop * from. It is written only by owner thread, via ordered store. * Both sp and base are allowed to wrap around on overflow, but * (sp - base) still estimates size. To improve array locality, * indices are occasionally renormalized to zero (see * tryInactivate). */ private int sp; /** * Index (mod queue.length) of least valid queue slot, which is * always the next position to steal from if nonempty. */ private volatile int base; /** * Activity status and pause control. When zero, this worker is * considered active. Nonzero values indicate number of empty * scans (see getStolenTask) to control pausing. The value must * be nonzero upon construction. It must be zero when executing * tasks, and BEFORE stealing a task. It must be nonzero before * blocking on the PoolBarrier. */ private int scans; /** * Seed for random number generator for choosing steal victims */ private int randomVictimSeed; /** * Number of steals, transferred to fullStealCount when idle */ private int stealCount; /** * Number of steals, just for monitoring purposes, */ private volatile long fullStealCount; /** * Seed for juRandom methods. */ private long juRandomSeed; /** * The last event count waited for */ private long eventCount; /** * Index of this worker in pool array. Set once by pool before running. */ private int poolIndex; // Padding to help avoid cacheline sharing across workers private int pad0, pad1, pad2, pad3, pad4, pad5, pad6, pad7; private int pad8, pad9, pada, padb, padc, padd, pade, padf; /** * Creates a ForkJoinWorkerThread operating in the given pool. * @param pool the pool this thread works in * @throws NullPointerException if pool is null; */ protected ForkJoinWorkerThread(ForkJoinPool pool) { if (pool == null) throw new NullPointerException(); this.pool = pool; this.runState = new RunState(); this.scans = 1; int rseed = randomSeedGenerator.nextInt(); this.randomVictimSeed = (rseed == 0)? 1 : rseed; // must be nonzero this.juRandomSeed = randomSeedGenerator.nextLong(); } // Initialization and access methods used by Pool final void setWorkerPoolIndex(int i) { poolIndex = i; } final int getWorkerPoolIndex() { return poolIndex; } final RunState getRunState() { return runState; } final long getWorkerStealCount() { return fullStealCount + stealCount; // can peek at local count too } // Primitive support for queue operations /** * Sets sp in store-order. */ private final void setSp(int s) { _unsafe.putOrderedInt(this, spOffset, s); } /** * Add in store-order the given task at given slot of q to * null. Caller must ensure q is nonnull and index is in range. */ private static final void setSlot(ForkJoinTask<?>[] q, int i, ForkJoinTask<?> t){ _unsafe.putOrderedObject(q, (i << qShift) + qBase, t); } /** * CAS given slot of q to null. Caller must ensure q is nonnull * and index is in range. */ private static final boolean casSlotNull(ForkJoinTask<?>[] q, int i, ForkJoinTask<?> t) { return _unsafe.compareAndSwapObject(q, (i << qShift) + qBase, t, null); } // Main queue methods /** * Returns an estimate of the number of tasks in the queue. */ final int getQueueSize() { int n = sp - base; return n < 0? 0 : n; // suppress momentarily negative values } /** * Pushes a task. Called only by current thread. * @param t the task. Caller must ensure nonnull */ final void pushTask(ForkJoinTask<?> t) { ForkJoinTask<?>[] q = queue; int mask = q.length - 1; int s = sp; setSp(s + 1); setSlot(q, s & mask, t); if (mask <= s + 1 - base) growQueue(); } /** * Tries to take a task from the base of the queue, failing if * either empty or contended. * @return a task, or null if none or contended. */ private final ForkJoinTask<?> deqTask() { ForkJoinTask<?> t; int i; int b = base; ForkJoinTask<?>[] q = queue; if (b - sp < 0 && q != null && (t = q[i = b & (q.length - 1)]) != null && casSlotNull(q, i, t)) { base = b + 1; return t; } return null; } /** * Returns a popped task, or null if empty. Called only by * current thread. */ final ForkJoinTask<?> popTask() { ForkJoinTask<?> t; int i; int s; ForkJoinTask<?>[] q = queue; if (q != null && (s = sp - 1) - base >= 0 && (t = q[i = s & (q.length - 1)]) != null && casSlotNull(q, i, t)) { setSp(s); return t; } return null; } /** * Same as popTask, but with implementation biased to expect a * task to be available */ private final ForkJoinTask<?> expectedPopTask() { int s; ForkJoinTask<?>[] q = queue; if (q != null) { int i = (q.length - 1) & (s = sp - 1); ForkJoinTask<?> t = q[i]; if (casSlotNull(q, i, t) && t != null) { setSp(s); return t; } } return null; } /** * Specialized version of popTask to pop only if * topmost element is the given task. * @param t the task to match (null is never matched) */ final boolean popIfNext(ForkJoinTask<?> t) { int s; ForkJoinTask<?>[] q = queue; if (t != null && q != null && casSlotNull(q, (q.length - 1) & (s = sp - 1), t)) { setSp(s); return true; } return false; } /** * Returns next task to pop. */ final ForkJoinTask<?> peekTask() { ForkJoinTask<?>[] q = queue; return q == null? null : q[(sp - 1) & (q.length - 1)]; } /** * Doubles queue array size. Transfers elements by emulating * steals (deqs) from old array and placing, oldest first, into * new array. */ private final void growQueue() { ForkJoinTask<?>[] oldQ = queue; int oldSize = oldQ.length; int newSize = oldSize << 1; if (newSize > MAXIMUM_QUEUE_CAPACITY) throw new RejectedExecutionException("Queue capacity exceeded"); ForkJoinTask<?>[] newQ = queue = new ForkJoinTask<?>[newSize]; int b = base; int bf = b + oldSize; int oldMask = oldSize - 1; int newMask = newSize - 1; do { int oldIndex = b & oldMask; ForkJoinTask<?> t = oldQ[oldIndex]; if (t != null && !casSlotNull(oldQ, oldIndex, t)) t = null; setSlot(newQ, b & newMask, t); } while (++b != bf); } // Activation control /** * Unconditionally set status to active and adjust activeCount */ private final void ensureActive() { if (scans != 0) { scans = 0; pool.incrementActiveCount(); } } /** * Try to activate but fail on contention on active worker counter * @return true if now active */ private final boolean tryActivate() { if (scans != 0) { if (!pool.tryIncrementActiveCount()) return false; scans = 0; } return true; } /** * Unconditionally inactivate. Does not block even if activeCount * now zero. (Use tryInactivate instead.) Needed for helpQuiesce. */ private final void ensureInactive() { if (scans == 0) { scans = 1; pool.decrementActiveCount(); } } /** * Possibly inactivate and block or pause waiting for work. If * pool is quiescent, before blocking, transfer local steal count * to volatile field. Also renormalizes queue indices to improve * future queue array locality. Note that this can cause ongoing * steals to momentarily believe queue is nonempty but will still * fail to extract a task, which at most may cause them to * unnecessarily activate, but even this is minimized by only * doing this upon quiesence. * * Precondition: Local queue is empty, and at least one full scan * of other worker queus and submissions failed to find a task. * * @return true if pool apparently idle on entry to this method */ private final boolean tryInactivate() { if (scans == 0 && !pool.tryDecrementActiveCount()) return false; ++scans; if (pool.getActiveThreadCount() != 0) { if (scans >= SCANS_PER_PAUSE) { scans = 1; pauseAwaitingWork(null); } return false; } if (sp != 0) { // renormalize indices setSp(0); base = 0; } int sc = stealCount; // accumulate steals if (sc != 0) { long fsc = fullStealCount + sc; stealCount = 0; fullStealCount = fsc; } eventCount = pool.barrierSync(eventCount); return true; } // Support for pausing when inactive /** * The number of empty steal attempts before pausing. Must be a * power of two. */ private static final int PROBES_PER_PAUSE = (1 << 10); /** * The number of empty scans (== probe each worker at least once) * before pausing. Based on actual number of processors, not * actual poolSize, since this better estimates effects of memory * stalls etc on larger machines. */ private static final int SCANS_PER_PAUSE = PROBES_PER_PAUSE / Runtime.getRuntime().availableProcessors(); /** * Politely stall when cannot find a task to run. First check run * status and cancel task if stopping. Currently, pauses are * implemented only as yield, but may someday incorporate advisory * blocking. * @param joinMe if nonnull, a task to cancel if stopping */ private final void pauseAwaitingWork(ForkJoinTask<?> joinMe) { if (runState.isAtLeastStopping()) { if (joinMe != null) joinMe.cancel(); } else Thread.yield(); } // Lifecycle methods /** * Initializes internal state after construction but before * processing any tasks. If you override this method, you must * invoke super.onStart() at the beginning of the method. * Initialization requires care: Most fields must have legal * default values, to ensure that attempted accesses from other * threads work correctly even before this thread starts * processing tasks. */ protected void onStart() { // wait for start signal before allocating queue array eventCount = pool.barrierSync(0); if (queue == null) queue = new ForkJoinTask<?>[INITIAL_QUEUE_CAPACITY]; } /** * Perform cleanup associated with termination of this worker * thread. If you override this method, you must invoke * super.onTermination at the end of the overridden method. * * @param exception the exception causing this thread to abort due * to an unrecoverable error, or null if completed normally. */ protected void onTermination(Throwable exception) { try { clearLocalTasks(); ensureInactive(); cancelTasks(); runState.transitionToTerminated(); } finally { pool.workerTerminated(this, exception); } } /** * This method is required to be public, but should never be * called explicitly. It performs the main run loop to execute * ForkJoinTasks. */ public void run() { try { onStart(); mainLoop(); onTermination(null); } catch (Throwable ex) { onTermination(ex); } } // Methods for running submissions, stolen and/or local tasks /** * Main run loop. On each step prefer running a submission * if previously inactive, else prefer stolen task. If a * task was run, also run any other subtasks it pushed; * otherwise inactivate. */ private final void mainLoop() { boolean preferSubmission = true; while (runState.isRunning()) { if ((preferSubmission || !runStolenTask()) && !runSubmission()) preferSubmission = !preferSubmission && tryInactivate(); else { runLocalTasks(); preferSubmission = false; } } } /** * Runs all tasks on local queue */ private final void runLocalTasks() { ForkJoinTask<?> t; while ((t = expectedPopTask()) != null) t.exec(); } /** * Runs a stolen task if one exists. * @return true if ran a task */ private final boolean runStolenTask() { ForkJoinTask<?> t = getStolenTask(); if (t != null) { t.exec(); return true; } return false; } /** * Runs a submission if one exists. * @return true if ran a task */ private final boolean runSubmission() { Submission<?> s = getSubmission(); if (s != null) { s.exec(); return true; } return false; } /** * Returns a submission, if one exists; activating first if necessary */ private final Submission<?> getSubmission() { while (pool.mayHaveQueuedSubmissions()) { Submission<?> s; if (tryActivate() && (s = pool.pollSubmission()) != null) return s; } return null; } /** * Runs one popped task, if available * @return true if ran a task */ private final boolean runLocalTask() { ForkJoinTask<?> t = popTask(); if (t != null) { t.exec(); return true; } return false; } /** * Pops or steals a task * @return task, or null if none available */ private final ForkJoinTask<?> getLocalOrStolenTask() { ForkJoinTask<?> t = popTask(); return t != null? t : getStolenTask(); } /** * Runs one popped or stolen task, if available * @return true if ran a task */ private final boolean runLocalOrStolenTask() { ForkJoinTask<?> t = getLocalOrStolenTask(); if (t != null) { t.exec(); return true; } return false; } /** * Runs tasks until activeCount zero */ private final void runUntilQuiescent() { for (;;) { ForkJoinTask<?> t = getLocalOrStolenTask(); if (t != null) { ensureActive(); t.exec(); } else { ensureInactive(); if (pool.getActiveThreadCount() == 0) { ensureActive(); // reactivate on exit break; } } } } // Stealing tasks /** * Computes next value for random victim probe. Scans don't * require a very high quality generator, but also not a crummy * one. Marsaglia xor-shift is cheap and works well. */ private static final int xorShift(int r) { r ^= r << 1; r ^= r >>> 3; return r ^ (r << 10); } /** * Tries to steal a task from another worker. Starts at a random * index of workers array, and probes workers until finding one * with non-empty queue or finding that all are empty. It * randomly selects the first n-1 probes. If these are empty, it * resorts to a full circular traversal, which is necessary to * accurately set active status by caller. * * This method must be both fast and quiet -- avoiding as much as * possible memory accesses that could disrupt cache sharing etc * other than those needed to check for and take tasks. This * accounts for, among other things, updating random seed in place * without storing it until exit. (Note that we only need to store * it if we found a task; otherwise it doesn't matter if we start * at the same place next time.) * * @return a task, or null if none found */ private final ForkJoinTask<?> getStolenTask() { final ForkJoinWorkerThread[] ws = pool.workers; final int mask = ws.length - 1; // must be power of 2 minus 1 int probes = -mask; // use random index while negative int r = randomVictimSeed; // extract once to keep scan quiet int idx = r; ForkJoinTask<?> t = null; do { ForkJoinWorkerThread v = ws[mask & idx]; r = xorShift(r); // update seed if (v != null && v.base - v.sp < 0) { // apparently nonempty if (tryActivate() && (t = v.deqTask()) != null) { randomVictimSeed = r; ++stealCount; break; } probes = -mask; // restart on contention idx = r; continue; } idx = probes < 0? r : (idx + 1); // n-1 random then circular } while (probes++ <= mask); return t; } /** * Tries to steal tasks while waiting for join. Similar to * getStolenTask except intersperses checks for completion and * shutdown. * @return a task, or null if joinMe is completed */ private final ForkJoinTask<?> scanWhileJoining(ForkJoinTask<?> joinMe) { ForkJoinWorkerThread[] ws = pool.workers; int mask = ws.length - 1; int r = randomVictimSeed; int idx = r; int probes = 0; ForkJoinTask<?> t = null; for (;;) { ForkJoinWorkerThread v = ws[idx & mask]; r = xorShift(r); if (joinMe.status < 0) break; if (v != null && (t = v.deqTask()) != null) { randomVictimSeed = r; ++stealCount; break; } if ((++probes & (PROBES_PER_PAUSE - 1)) == 0) pauseAwaitingWork(joinMe); idx = probes <= mask? r: (idx + 1); // n-1 random then circular } return t; } // Support for core ForkJoinTask methods /** * Implements ForkJoinTask.quietlyJoin */ final void helpJoinTask(ForkJoinTask<?> joinMe) { ForkJoinTask<?> t; while (joinMe.status >= 0 && ((t = popTask()) != null || (t = scanWhileJoining(joinMe)) != null)) t.exec(); } /** * Implements RecursiveAction.forkJoin */ final void doForkJoin(RecursiveAction t1, RecursiveAction t2) { if (t1.status >= 0 && t2.status >= 0) { pushTask(t2); if (t1.rawExec()) { if (popIfNext(t2)) { if (t2.rawExec()) return; } else { helpJoinTask(t2); if (t2.completedNormally()) return; } } } Throwable ex; if ((ex = t1.getException()) != null) t2.cancel(); else if ((ex = t2.getException()) != null) t1.cancel(); if (ex != null) ForkJoinTask.rethrowException(ex); } /** * Timeout version of helpJoin needed for Submission class * Returns false if timed out before complated */ final boolean doTimedJoinTask(ForkJoinTask<?> joinMe, long nanos) { long startTime = System.nanoTime(); int spins = 0; for (;;) { ForkJoinTask<?> t = popTask(); if (joinMe.isDone()) return true; else if ((t = getLocalOrStolenTask())!= null) t.exec(); else if (runState.isAtLeastStopping()) return false; else if (nanos - (System.nanoTime() - startTime) <= 0) return false; } } // Cleanup support /** * Run or cancel all local tasks on exit from main. */ private final void clearLocalTasks() { while (sp - base > 0) { ForkJoinTask<?> t = popTask(); if (t != null) { if (runState.isAtLeastStopping()) t.setCancelled(); // avoid exceptions due to cancel() else t.exec(); } } } /** * Removes and cancels all tasks in queue. Can be called from any * thread. */ final void cancelTasks() { while (sp - base > 0) { ForkJoinTask<?> t = deqTask(); if (t != null) // avoid exceptions due to cancel() t.setCancelled(); } } // Public methods on current thread /** * Returns the pool hosting the current task execution. * @return the pool */ public static ForkJoinPool getPool() { return ((ForkJoinWorkerThread)(Thread.currentThread())).pool; } /** * Returns the index number of the current worker thread in its * pool. The return value is in the range * <tt>0...getPool().getPoolSize()-1</tt>. This method may be * useful for applications that track status or collect results * per-worker rather than per-task. * @return the index number. */ public static int getPoolIndex() { return ((ForkJoinWorkerThread)(Thread.currentThread())).poolIndex; } /** * Returns an estimate of the number of tasks waiting to be run by * the current worker thread. This value may be useful for * heuristic decisions about whether to fork other tasks. * @return the number of tasks */ public static int getLocalQueueSize() { return ((ForkJoinWorkerThread)(Thread.currentThread())). getQueueSize(); } /** * Returns, but does not remove or execute, the next task locally * queued for execution by the current worker thread. There is no * guarantee that this task will be the next one actually returned * or executed from other polling or execution methods. * @return the next task or null if none */ public static ForkJoinTask<?> peekLocalTask() { return ((ForkJoinWorkerThread)(Thread.currentThread())).peekTask(); } /** * Removes and returns, without executing, the next task queued * for execution in the current worker thread's local queue. * @return the next task to execute, or null if none */ public static ForkJoinTask<?> pollLocalTask() { return ((ForkJoinWorkerThread)(Thread.currentThread())).popTask(); } /** * Execute the next task locally queued by the current worker, if * one is available. * @return true if a task was run; a false return indicates * that no task was available. */ public static boolean executeLocalTask() { return ((ForkJoinWorkerThread)(Thread.currentThread())). runLocalTask(); } /** * Removes and returns, without executing, the next task queued * for execution in the current worker thread's local queue or if * none, a task stolen from another worker, if one is available. * A null return does not necessarily imply that all tasks are * completed, only that there are currently none available. * @return the next task to execute, or null if none */ public static ForkJoinTask<?> pollTask() { return ((ForkJoinWorkerThread)(Thread.currentThread())). getLocalOrStolenTask(); } /** * Helps this program complete by processing a local, stolen or * submitted task, if one is available. This method may be useful * when several tasks are forked, and only one of them must be * joined, as in: * <pre> * while (!t1.isDone() && !t2.isDone()) * ForkJoinWorkerThread.executeTask(); * </pre> * * @return true if a task was run; a false return indicates * that no task was available. */ public static boolean executeTask() { return ((ForkJoinWorkerThread)(Thread.currentThread())). runLocalOrStolenTask(); } /** * Executes tasks (but not new submissions) until the pool * isQuiescent. */ public static void helpQuiesce() { ((ForkJoinWorkerThread)(Thread.currentThread())). runUntilQuiescent(); } /** * Returns an estimate of how many more locally queued tasks there * are than idle worker 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 number (for * example, 3) stealable tasks, plus more if there are idle * workers. * * <p><b>Sample Usage.</b> Here is a variant version of * <tt>compute</tt> for the {@link BinaryAsyncAction} Fib example * using getEstimatedSurplusTaskCount to dynamically determine * sequential threshold: * * <pre> * protected void compute() { * Fib f = this; * while (f.n > 1 && * ForkJoinWorkerThread.getEstimatedSurplusTaskCount() <= 3) { * Fib left = new Fib(f.n - 1); * Fib right = new Fib(f.n - 2); * f.linkSubtasks(left, right); * right.fork(); // fork right * f = left; // loop on left * } * f.result = sequentiallyComputeFibinacci(f.n); * f.finish(); * } * } * </pre> * * @return the number of tasks, which is negative if there are * fewer tasks than idle workers */ public static int getEstimatedSurplusTaskCount() { return ((ForkJoinWorkerThread)(Thread.currentThread())) .estimatedSurplusTaskCount(); } final int estimatedSurplusTaskCount() { return (sp - base) - pool.getIdleThreadCount(); } /** * Removes and returns, without executing, the given task from the * queue hosting current execution only if it would be the next * task executed by the current worker. Among other usages, this * method may be used to bypass task execution during * cancellation. * * <p><b>Sample Usage,</b> This method may help counterbalance * effects of dynamic task thresholding. If using a threshold that * typically generates too many tasks, then this method may be * used to more cheaply execute excess ones. Here is a dynamically * tuned version of the {@link RecursiveAction} Applyer example: * * <pre> * class Applyer extends RecursiveAction { * final double[] array; * final int lo, hi, seqSize; * double result; * Applyer next; // keeps track of right-hand-side tasks * Applyer(double[] array, int lo, int hi, int seqSize, Applyer next) { * this.array = array; this.lo = lo; this.hi = hi; * this.seqSize = seqSize; this.next = next; * } * * double atLeaf(int l, int r) { * double sum = 0; * for (int i = l; i < h; ++i) // perform leftmost base step * sum += array[i] * array[i]; * return sum; * } * * protected void compute() { * int l = lo; * int h = hi; * Applyer right = null; * while (h - l > 1 && * ForkJoinWorkerThread.getEstimatedSurplusTaskCount() <= 3) { * int mid = (l + h) >>> 1; * right = new Applyer(array, mid, h, seqSize, right); * right.fork(); * h = mid; * } * double sum = atLeaf(l, h); * while (right != null && // direct compute unstolen tasks * ForkJoinWorkerThread.removeIfNextLocalTask(right)) { * sum += right.atLeaf(r.lo, r.hi); * right = right.next; * } * while (right != null) { // join remaining right-hand sides * right.join(); * sum += right.result; * right = right.next; * } * result = sum; * } * } * </pre> * * @param task the task * @return true if removed */ public static boolean removeIfNextLocalTask(ForkJoinTask<?> task) { return ((ForkJoinWorkerThread)(Thread.currentThread())).popIfNext(task); } // Support for alternate handling of submissions /** * Removes and returns the next unexecuted submission to the given * pool, if one is available. To access a submission from the * current worker's pool, use <tt>pollSubmission(getPool())</tt>. * This method may be useful for draining tasks during exception * recovery and for re-assigning work in systems with multiple * pools. * @param pool the pool * @return the next submission, or null if none */ public static Future<?> pollSubmission(ForkJoinPool pool) { return pool.pollSubmission(); } /** * If the given argument represents a submission to a ForkJoinPool * (normally, one returned by <tt>pollSubmission</tt>), returns * the actual task submitted to the pool. This method may be * useful for alternate handling of drained submissions.. * @param submission the submission * @return the underlying task * @throws IllegalArgumentException if the given future does * not represent a submission to a pool */ public static <V> ForkJoinTask<V> getSubmittedTask(Future<V> submission) { try { return ((Submission)submission).getSubmittedTask(); } catch (ClassCastException ex) { throw new IllegalArgumentException(); } } /** * If the argument represents a submission to a ForkJoinPool * (normally, one returned by <tt>pollSubmission</tt>), causes it * to be ready with the given value returned upon invocation of * its <tt>get()</tt> method, regardless of the status of the * underlying ForkJoinTask. This method may be useful for * alternate handling of drained submissions.. * @param submission the submission * @param value the result to be returned by the submission * @throws IllegalArgumentException if the given future does * not represent a submission to a pool */ public static <V> void forceCompletion(Future<V> submission, V value) { try { ((Submission)submission).finishTask(value); } catch (ClassCastException ex) { throw new IllegalArgumentException(); } } /** * If the argument represents a submission to a ForkJoinPool * (normally, one returned by <tt>pollSubmission</tt>), causes it * to be ready with the given exception thrown on invocation of * its <tt>get()</tt> method, regardless of the status of the * underlying ForkJoinTask..This method may be useful for * alternate handling of drained submissions.. * @param submission the submission * @param exception the exception to be thrown on access * @throws IllegalArgumentException if the exception is * not a RuntimeException or Error * @throws IllegalArgumentException if the given future does * not represent a submission to a pool */ public static <V> void forceCompletionExceptionally(Future<V> submission, Throwable exception) { if (!(exception instanceof RuntimeException) && !(exception instanceof Error)) throw new IllegalArgumentException(); try { ((Submission)submission).finishTaskExceptionally(exception); } catch (ClassCastException ex) { throw new IllegalArgumentException(); } } // Per-worker exported random numbers // Same constants as java.util.Random final static long JURandomMultiplier = 0x5DEECE66DL; final static long JURandomAddend = 0xBL; final static long JURandomMask = (1L << 48) - 1; private final int nextJURandom(int bits) { long next = (juRandomSeed * JURandomMultiplier + JURandomAddend) & JURandomMask; juRandomSeed = next; return (int)(next >>> (48 - bits)); } private final int nextJURandomInt(int n) { if (n <= 0) throw new IllegalArgumentException("n must be positive"); int bits = nextJURandom(31); if ((n & -n) == n) return (int)((n * (long)bits) >> 31); for (;;) { int val = bits % n; if (bits - val + (n-1) >= 0) return val; bits = nextJURandom(31); } } private final long nextJURandomLong() { return ((long)(nextJURandom(32)) << 32) + nextJURandom(32); } private final long nextJURandomLong(long n) { if (n <= 0) throw new IllegalArgumentException("n must be positive"); long offset = 0; while (n >= Integer.MAX_VALUE) { // randomly pick half range int bits = nextJURandom(2); // 2nd bit for odd vs even split long half = n >>> 1; long nextn = ((bits & 2) == 0)? half : n - half; if ((bits & 1) == 0) offset += n - nextn; n = nextn; } return offset + nextJURandomInt((int)n); } private final double nextJURandomDouble() { return (((long)(nextJURandom(26)) << 27) + nextJURandom(27)) / (double)(1L << 53); } /** * Returns a random integer using a per-worker random * number generator with the same properties as * {@link java.util.Random#nextInt} * @return the next pseudorandom, uniformly distributed {@code int} * value from this worker's random number generator's sequence */ public static int nextRandomInt() { return ((ForkJoinWorkerThread)(Thread.currentThread())). nextJURandom(32); } /** * Returns a random integer using a per-worker random * number generator with the same properties as * {@link java.util.Random#nextInt(int)} * @param n the bound on the random number to be returned. Must be * positive. * @return the next pseudorandom, uniformly distributed {@code int} * value between {@code 0} (inclusive) and {@code n} (exclusive) * from this worker's random number generator's sequence * @throws IllegalArgumentException if n is not positive */ public static int nextRandomInt(int n) { return ((ForkJoinWorkerThread)(Thread.currentThread())). nextJURandomInt(n); } /** * Returns a random long using a per-worker random * number generator with the same properties as * {@link java.util.Random#nextLong} * @return the next pseudorandom, uniformly distributed {@code long} * value from this worker's random number generator's sequence */ public static long nextRandomLong() { return ((ForkJoinWorkerThread)(Thread.currentThread())). nextJURandomLong(); } /** * Returns a random integer using a per-worker random * number generator with the same properties as * {@link java.util.Random#nextInt(int)} * @param n the bound on the random number to be returned. Must be * positive. * @return the next pseudorandom, uniformly distributed {@code int} * value between {@code 0} (inclusive) and {@code n} (exclusive) * from this worker's random number generator's sequence * @throws IllegalArgumentException if n is not positive */ public static long nextRandomLong(long n) { return ((ForkJoinWorkerThread)(Thread.currentThread())). nextJURandomLong(n); } /** * Returns a random double using a per-worker random * number generator with the same properties as * {@link java.util.Random#nextDouble} * @return the next pseudorandom, uniformly distributed {@code double} * value between {@code 0.0} and {@code 1.0} from this * worker's random number generator's sequence */ public static double nextRandomDouble() { return ((ForkJoinWorkerThread)(Thread.currentThread())). nextJURandomDouble(); } // Temporary Unsafe mechanics for preliminary release static final Unsafe _unsafe; static final long baseOffset; static final long spOffset; static final long qBase; static final int qShift; static { try { if (ForkJoinWorkerThread.class.getClassLoader() != null) { Field f = Unsafe.class.getDeclaredField("theUnsafe"); f.setAccessible(true); _unsafe = (Unsafe)f.get(null); } else _unsafe = Unsafe.getUnsafe(); baseOffset = _unsafe.objectFieldOffset (ForkJoinWorkerThread.class.getDeclaredField("base")); spOffset = _unsafe.objectFieldOffset (ForkJoinWorkerThread.class.getDeclaredField("sp")); qBase = _unsafe.arrayBaseOffset(ForkJoinTask[].class); int s = _unsafe.arrayIndexScale(ForkJoinTask[].class); if ((s & (s-1)) != 0) throw new Error("data type scale not a power of two"); qShift = 31 - Integer.numberOfLeadingZeros(s); } catch (Exception e) { throw new RuntimeException("Could not initialize intrinsics", e); } } }