/* * 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 java.util.*; import java.util.concurrent.*; import java.util.concurrent.locks.*; import java.util.concurrent.atomic.*; import sun.misc.Unsafe; import java.lang.reflect.*; /** * Host for a group of ForkJoinWorkerThreads that perform * ForkJoinTasks. A ForkJoinPool also provides the entry point for * tasks submitted from non-ForkJoinTasks, as well as management and * monitoring operations. Normally a single ForkJoinPool is used for * a large number of submitted tasks. Otherwise, use would not always * outweigh the construction overhead of creating a large set of * threads and the associated startup bookkeeping. * * <p> Class ForkJoinPool does not implement the ExecutorService * interface because it only executes ForkJoinTasks, not arbitrary * Runnables. However, for the sake of uniformity, it supports * analogous lifecycle control methods such as shutdown. * * <p>A ForkJoinPool may be constructed with any number of worker * threads, and worker threads may be added and removed dynamically. * However, as a general rule, using a pool size of the number of * processors on a given system (as arranged by the default * constructor) will result in the best performance. Resizing may be * expensive and may cause transient imbalances and slowdowns. * * <p>In addition to execution and lifecycle control methods, this * class provides status check methods (for example * <tt>getStealCount</tt>) that are intended to aid in developing, * tuning, and monitoring fork/join applications. */ public class ForkJoinPool implements ForkJoinExecutor { /* * This is an overhauled version of the framework described in "A * Java Fork/Join Framework" by Doug Lea, in, Proceedings, ACM * JavaGrande Conference, June 2000 * (http://gee.cs.oswego.edu/dl/papers/fj.pdf). It retains most of * the basic structure, but includes a number of algorithmic * improvements, along with integration with other * java.util.concurrent components. */ /** * Factory for creating new ForkJoinWorkerThreads. A * ForkJoinWorkerThreadFactory must be defined and used for * ForkJoinWorkerThread subclasses that extend base functionality * or initialize threads with different contexts. */ public static interface ForkJoinWorkerThreadFactory { /** * Returns a new worker thread operating in the given pool. * * @param pool the pool this thread works in * @throws NullPointerException if pool is null; */ public ForkJoinWorkerThread newThread(ForkJoinPool pool); } /** * The default ForkJoinWorkerThreadFactory, used unless overridden * in ForkJoinPool constructors. */ public static class DefaultForkJoinWorkerThreadFactory implements ForkJoinWorkerThreadFactory { public ForkJoinWorkerThread newThread(ForkJoinPool pool) { return new ForkJoinWorkerThread(pool); } } private static final DefaultForkJoinWorkerThreadFactory defaultForkJoinWorkerThreadFactory = new DefaultForkJoinWorkerThreadFactory(); /** * Permission required for callers of methods that may start or * kill threads. */ private static final RuntimePermission modifyThreadPermission = new RuntimePermission("modifyThread"); /** * If there is a security manager, makes sure caller has * permission to modify threads. */ private static void checkPermission() { SecurityManager security = System.getSecurityManager(); if (security != null) security.checkPermission(modifyThreadPermission); } /** * Generator for assigning sequence numbers as thread names. */ private static final AtomicInteger poolNumberGenerator = new AtomicInteger(); /** * Array holding all worker threads in the pool. Array size must * be a power of two. Acts similarly to a CopyOnWriteArrayList -- * updates are protected by workerLock. But it additionally * allows in-place nulling out or replacements of slots upon * termination. All uses of this array should first assign as * local, and must screen out nulls. Note: ForkJoinWorkerThreads * directly access this array. */ volatile ForkJoinWorkerThread[] workers; /** * Pool wide synchronization control. Workers are enabled to look * for work when the barrier's count is incremented. If they fail * to find some, they may wait for next count. Synchronization * events occur only in enough contexts to maintain overall * liveness: * * - Submission of a new task * - Termination of pool or worker * * So, signals and waits occur relatively rarely during normal * processing, which minimizes contention on this global * synchronizer. Even so, the PoolBarrier is designed to minimize * blockages by threads that have better things to do. */ private final PoolBarrier poolBarrier; /** * Lock protecting access to workers. */ private final ReentrantLock workerLock; /** * Condition for awaitTermination. */ private final Condition termination; /** * Lifecycle control. */ private final RunState runState; /** * The number of submissions that are running in pool. */ private final AtomicInteger runningSubmissions; /** * The uncaught exception handler used when any worker * abrupty terminates */ private Thread.UncaughtExceptionHandler ueh; /** * Creation factory for worker threads. */ private final ForkJoinWorkerThreadFactory factory; /** * Head and tail of embedded submission queue. (The queue is * embedded to avoid hostile memory placements.) */ private volatile SQNode sqHead; private volatile SQNode sqTail; /** * Number of workers that are (probably) executing tasks. * Atomically incremented when a worker gets a task to run, and * decremented when worker has no tasks and cannot find any. This * is updated only via CAS. It is inlined here rather than a * stand-alone field to minimize memory thrashing when it is * heavily contended during ramp-up/down of tasks. */ private volatile int activeCount; /** * The current targetted pool size. Updated only under worker lock * but volatile to allow concurrent reads. */ private volatile int poolSize; /** * The number of workers that have started but not yet terminated * Accessed only under workerLock. */ private int runningWorkers; /** * Pool number, just for assigning useful names to worker threads */ private final int poolNumber; /** * Return a good size for worker array given pool size. * Currently requires size to be a power of two. */ private static int workerSizeFor(int ps) { return ps <= 1? 1 : (1 << (32 - Integer.numberOfLeadingZeros(ps-1))); } /** * Create new worker using factory. * @param index the index to assign worker */ private ForkJoinWorkerThread createWorker(int index) { ForkJoinWorkerThread w = factory.newThread(this); w.setDaemon(true); w.setWorkerPoolIndex(index); w.setName("ForkJoinPool-" + poolNumber + "-worker-" + index); Thread.UncaughtExceptionHandler h = ueh; if (h != null) w.setUncaughtExceptionHandler(h); return w; } /** * Creates a ForkJoinPool with a pool size equal to the number of * processors available on the system and using the default * ForkJoinWorkerThreadFactory, * @throws SecurityException if a security manager exists and * the caller is not permitted to modify threads * because it does not hold {@link * java.lang.RuntimePermission}<tt>("modifyThread")</tt>, */ public ForkJoinPool() { this(Runtime.getRuntime().availableProcessors(), defaultForkJoinWorkerThreadFactory); } /** * Creates a ForkJoinPool with the indicated number of Worker * threads, and using the default ForkJoinWorkerThreadFactory, * @param poolSize the number of worker threads * @throws IllegalArgumentException if poolSize less than or * equal to zero * @throws SecurityException if a security manager exists and * the caller is not permitted to modify threads * because it does not hold {@link * java.lang.RuntimePermission}<tt>("modifyThread")</tt>, */ public ForkJoinPool(int poolSize) { this(poolSize, defaultForkJoinWorkerThreadFactory); } /** * Creates a ForkJoinPool with a pool size equal to the number of * processors available on the system and using the given * ForkJoinWorkerThreadFactory, * @param factory the factory for creating new threads * @throws NullPointerException if factory is null * @throws SecurityException if a security manager exists and * the caller is not permitted to modify threads * because it does not hold {@link * java.lang.RuntimePermission}<tt>("modifyThread")</tt>, */ public ForkJoinPool(ForkJoinWorkerThreadFactory factory) { this(Runtime.getRuntime().availableProcessors(), factory); } /** * Creates a ForkJoinPool with the indicated number of worker * threads and the given factory. * * <p> You can also add and remove threads while the pool is * running. But it is generally more efficient and leads to more * predictable performance to initialize the pool with a * sufficient number of threads to support the desired concurrency * level and leave this value fixed. * * @param poolSize the number of worker threads * @param factory the factory for creating new threads * @throws IllegalArgumentException if poolSize less than or * equal to zero * @throws NullPointerException if factory is null * @throws SecurityException if a security manager exists and * the caller is not permitted to modify threads * because it does not hold {@link * java.lang.RuntimePermission}<tt>("modifyThread")</tt>, */ public ForkJoinPool(int poolSize, ForkJoinWorkerThreadFactory factory) { if (poolSize <= 0) throw new IllegalArgumentException(); if (factory == null) throw new NullPointerException(); checkPermission(); this.poolSize = poolSize; this.factory = factory; this.poolNumber = poolNumberGenerator.incrementAndGet(); this.poolBarrier = new PoolBarrier(); this.runState = new RunState(); this.runningSubmissions = new AtomicInteger(); this.workerLock = new ReentrantLock(); this.termination = workerLock.newCondition(); SQNode dummy = new SQNode(null); this.sqHead = dummy; this.sqTail = dummy; createAndStartWorkers(poolSize); } /** * Initial worker array and worker creation and startup. (This * must be done under lock to avoid interference by some of the * newly started threads while creating others.) */ private void createAndStartWorkers(int ps) { final ReentrantLock lock = this.workerLock; lock.lock(); try { ForkJoinWorkerThread[] ws = new ForkJoinWorkerThread[workerSizeFor(ps)]; workers = ws; for (int i = 0; i < ps; ++i) ws[i] = createWorker(i); for (int i = 0; i < ps; ++i) { ws[i].start(); ++runningWorkers; } } finally { lock.unlock(); } } /** * Performs the given task; returning its result upon completion * @param task the task * @return the task's result * @throws NullPointerException if task is null * @throws RejectedExecutionException if pool is shut down */ public <T> T invoke(ForkJoinTask<T> task) { return doSubmit(task).awaitInvoke(); } /** * Arranges for (asynchronous) execution of the given task, * returning a {@link Future} that may be used to obtain results * upon completion. (The only supported operations on this object * are those defined in the <tt>Future</tt> interface.) * @param task the task * @return a Future that can be used to get the task's results. * @throws NullPointerException if task is null * @throws RejectedExecutionException if pool is shut down */ public <T> Future<T> submit(ForkJoinTask<T> task) { return doSubmit(task); } /** * Arranges for (asynchronous) execution of the given task. * @param task the task * @throws NullPointerException if task is null * @throws RejectedExecutionException if pool is shut down */ public <T> void execute(ForkJoinTask<T> task) { doSubmit(task); } /** * Common code for invoke and submit */ private <T> Submission<T> doSubmit(ForkJoinTask<T> task) { if (task == null) throw new NullPointerException(); if (runState.isAtLeastShutdown()) throw new RejectedExecutionException(); Submission<T> job = new Submission<T>(task, this); addSubmission(job); poolBarrier.signal(); return job; } /** * Returns the targeted number of worker threads in this pool. * This value does not necessarily reflect transient changes as * threads are added, removed, or abruptly terminate. * * @return the number of worker threads in this pool */ public int getPoolSize() { return poolSize; } /** * Equivalent to {@link #getPoolSize}. * * @return the number of worker threads in this pool */ public int getParallelismLevel() { return poolSize; } /** * Returns the number of worker threads that have started but not * yet terminated. This result returned by this method may differ * from <tt>getPoolSize</tt> when threads are added, removed, or * abruptly terminate. * * @return the number of worker threads */ public int getRunningWorkerCount() { int r; final ReentrantLock lock = this.workerLock; lock.lock(); try { r = runningWorkers; } finally { lock.unlock(); } return r; } /** * Sets the handler for internal worker threads that terminate due * to unrecoverable errors encountered while executing tasks. * Unless set, the current default or ThreadGroup handler is used * as handler. * * @param h the new handler * @return the old handler, or null if none * @throws SecurityException if a security manager exists and * the caller is not permitted to modify threads * because it does not hold {@link * java.lang.RuntimePermission}<tt>("modifyThread")</tt>, */ public Thread.UncaughtExceptionHandler setUncaughtExceptionHandler(Thread.UncaughtExceptionHandler h) { checkPermission(); Thread.UncaughtExceptionHandler old = null; final ReentrantLock lock = this.workerLock; lock.lock(); try { old = ueh; ueh = h; ForkJoinWorkerThread[] ws = workers; for (int i = 0; i < ws.length; ++i) { ForkJoinWorkerThread w = ws[i]; if (w != null) w.setUncaughtExceptionHandler(h); } } finally { lock.unlock(); } return old; } /** * Returns the handler for internal worker threads that terminate * due to unrecoverable errors encountered while executing tasks. * @return the handler, or null if none */ public Thread.UncaughtExceptionHandler getUncaughtExceptionHandler() { Thread.UncaughtExceptionHandler h; final ReentrantLock lock = this.workerLock; lock.lock(); try { h = ueh; } finally { lock.unlock(); } return h; } /** * Tries to adds the indicated number of new worker threads to the * pool. This method may be used to increase the amount of * parallelism available to tasks. The actual number of * threads added may be less than requested if the pool * is terminating or terminated * @return the number of threads added * @throws SecurityException if a security manager exists and * the caller is not permitted to modify threads * because it does not hold {@link * java.lang.RuntimePermission}<tt>("modifyThread")</tt>, */ public int addWorkers(int numberToAdd) { int nadded = 0; checkPermission(); final ReentrantLock lock = this.workerLock; lock.lock(); try { if (!runState.isAtLeastStopping()) { ForkJoinWorkerThread[] ws = workers; int len = ws.length; int newLen = len + numberToAdd; int newSize = workerSizeFor(newLen); ForkJoinWorkerThread[] nws = new ForkJoinWorkerThread[newSize]; System.arraycopy(ws, 0, nws, 0, len); for (int i = len; i < newLen; ++i) nws[i] = createWorker(i); workers = nws; for (int i = len; i < newLen; ++i) { nws[i].start(); ++runningWorkers; } poolSize += numberToAdd; nadded = numberToAdd; } } finally { lock.unlock(); } return nadded; } /** * Tries to remove the indicated number of worker threads from the * pool. The workers will exit the next time they are idle. This * method may be used to decrease the amount of parallelism * available to tasks. The actual number of workers removed * may be less than requested if the pool size would become * zero or the pool is terminating or terminated. * @return the number removed. * @throws SecurityException if a security manager exists and * the caller is not permitted to modify threads * because it does not hold {@link * java.lang.RuntimePermission}<tt>("modifyThread")</tt>, */ public int removeWorkers(int numberToRemove) { int nremoved = 0; checkPermission(); final ReentrantLock lock = this.workerLock; lock.lock(); try { // shutdown in rightmost order to enable shrinkage in // workerTerminated ForkJoinWorkerThread[] ws = workers; int k = ws.length; while (!runState.isAtLeastStopping() && --k > 0 && // don't kill ws[0] nremoved < numberToRemove) { ForkJoinWorkerThread w = ws[k]; if (w != null) { RunState rs = w.getRunState(); if (rs.transitionToShutdown()) { --poolSize; ++nremoved; } } } } finally { lock.unlock(); } return nremoved; } /** * Tries to add or remove workers to attain the given pool size. * This may fail to attain the given target if the pool is * terminating or terminated. * @param newSize the target poolSize * @return the pool size upon exit of this method * @throws IllegalArgumentException if newSize less than or * equal to zero * @throws SecurityException if a security manager exists and * the caller is not permitted to modify threads * because it does not hold {@link * java.lang.RuntimePermission}<tt>("modifyThread")</tt>, */ public int setPoolSize(int newSize) { checkPermission(); if (newSize <= 0) throw new IllegalArgumentException(); final ReentrantLock lock = this.workerLock; lock.lock(); try { int ps = poolSize; if (newSize > ps) addWorkers(newSize - ps); else if (newSize < ps) removeWorkers(ps - newSize); } finally { lock.unlock(); } return poolSize; } /** * Callback from terminating worker. * @param w the worker * @param ex the exception causing abrupt termination, or null if * completed normally */ final void workerTerminated(ForkJoinWorkerThread w, Throwable ex) { try { final ReentrantLock lock = this.workerLock; lock.lock(); try { // Unless stopping, null slot, and if rightmost slots // now null, shrink if (!runState.isAtLeastStopping()) { int idx = w.getWorkerPoolIndex(); ForkJoinWorkerThread[] ws = workers; int len = ws.length; if (idx >= 0 && idx < len && ws[idx] == w) { ws[idx] = null; int newlen = len; while (newlen > 0 && ws[newlen-1] == null) --newlen; if (newlen < len) { int newSize = workerSizeFor(newlen); if (newSize < len) { ForkJoinWorkerThread[] nws = new ForkJoinWorkerThread[newSize]; System.arraycopy(ws, 0, nws, 0, newlen); workers = nws; poolBarrier.signal(); } } } } if (--runningWorkers == 0) { terminate(); // no-op if already stopping runState.transitionToTerminated(); termination.signalAll(); } } finally { lock.unlock(); } } finally { if (ex != null) ForkJoinTask.rethrowException(ex); } } // lifecycle control /** * Initiates an orderly shutdown in which previously submitted * tasks are executed, but no new tasks will be accepted. * Invocation has no additional effect if already shut down. * Tasks that are in the process of being submitted concurrently * during the course of this method may or may not be rejected. * @throws SecurityException if a security manager exists and * the caller is not permitted to modify threads * because it does not hold {@link * java.lang.RuntimePermission}<tt>("modifyThread")</tt>, */ public void shutdown() { checkPermission(); runState.transitionToShutdown(); tryTerminateOnShutdown(); } /** * Attempts to stop all actively executing tasks, and cancels all * waiting tasks. Tasks that are in the process of being * submitted or executed concurrently during the course of this * method may or may not be rejected. * @throws SecurityException if a security manager exists and * the caller is not permitted to modify threads * because it does not hold {@link * java.lang.RuntimePermission}<tt>("modifyThread")</tt>, */ public void shutdownNow() { checkPermission(); terminate(); } /** * Returns <tt>true</tt> if this pool has been shut down. * * @return <tt>true</tt> if this pool has been shut down */ public boolean isShutdown() { return runState.isAtLeastShutdown(); } /** * Returns <tt>true</tt> if all tasks have completed following shut down. * * @return <tt>true</tt> if all tasks have completed following shut down */ public boolean isTerminated() { return runState.isTerminated(); } /** * Returns <tt>true</tt> if termination has commenced but has * not yet completed. * * @return <tt>true</tt> if in the process of terminating */ public boolean isTerminating() { return runState.isStopping(); } /** * Blocks until all tasks have completed execution after a shutdown * request, or the timeout occurs, or the current thread is * interrupted, whichever happens first. * * @param timeout the maximum time to wait * @param unit the time unit of the timeout argument * @return <tt>true</tt> if this executor terminated and * <tt>false</tt> if the timeout elapsed before termination * @throws InterruptedException if interrupted while waiting */ public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException { long nanos = unit.toNanos(timeout); final ReentrantLock lock = this.workerLock; lock.lock(); try { for (;;) { if (runState.isTerminated()) return true; if (nanos <= 0) return false; nanos = termination.awaitNanos(nanos); } } finally { lock.unlock(); } } /** * Initiate termination. */ private void terminate() { if (runState.transitionToStopping()) { stopAllWorkers(); cancelQueuedSubmissions(); cancelQueuedWorkerTasks(); interruptUnterminatedWorkers(); } } /** * Check for termination in shutdown state */ private void tryTerminateOnShutdown() { if (runState.isAtLeastShutdown() && runningSubmissions.get() == 0 && !hasQueuedSubmissions() && runningSubmissions.get() == 0) // recheck terminate(); } /** * Clear out and cancel submissions */ private void cancelQueuedSubmissions() { Submission<?> task; while (hasQueuedSubmissions() && (task = pollSubmission()) != null) task.cancel(false); } /** * Clean out worker queues. */ private void cancelQueuedWorkerTasks() { final ReentrantLock lock = this.workerLock; lock.lock(); try { ForkJoinWorkerThread[] ws = workers; for (int i = 0; i < ws.length; ++i) { ForkJoinWorkerThread t = ws[i]; if (t != null) t.cancelTasks(); } } finally { lock.unlock(); } } /** * Set each worker's status to stopping. Requires lock to avoid * conflicts with add/remove */ private void stopAllWorkers() { final ReentrantLock lock = this.workerLock; lock.lock(); try { ForkJoinWorkerThread[] ws = workers; for (int i = 0; i < ws.length; ++i) { ForkJoinWorkerThread t = ws[i]; if (t != null) { RunState rs = t.getRunState(); rs.transitionToStopping(); } } } finally { lock.unlock(); } poolBarrier.signal(); } /** * Interrupt all unterminated workers. This is not required for * sake of internal control, but may help unstick user code during * shutdown. */ private void interruptUnterminatedWorkers() { final ReentrantLock lock = this.workerLock; lock.lock(); try { ForkJoinWorkerThread[] ws = workers; for (int i = 0; i < ws.length; ++i) { ForkJoinWorkerThread t = ws[i]; if (t != null) { RunState rs = t.getRunState(); if (!rs.isTerminated()) { try { t.interrupt(); } catch (SecurityException ignore) { } } } } } finally { lock.unlock(); } } // Status queries /** * Returns true if all worker threads are currently idle. An idle * worker is one that cannot obtain a task to execute because none * are available to steal from other threads, and there are no * pending submissions to the pool. This method is conservative: * It might not return true immediately upon idleness of all * threads, but will eventually become true if threads remain * inactive. * @return true if all threads are currently idle */ public final boolean isQuiescent() { return activeCount == 0; } /** * Returns the approximate number of threads that are * currently executing tasks. This method may overestimate * the number of active threads. * @return the number of active threads. */ public final int getActiveThreadCount() { return activeCount; } /** * Returns the approximate number of threads that are currently * idle waiting for tasks. This method may underestimate the * number of idle threads. * @return the number of idle threads. */ public final int getIdleThreadCount() { return poolSize - activeCount; } /** * Returns the total number of tasks stolen from one thread's work * queue by another. This value is only an approximation, obtained * by iterating across all threads in the pool, and may * mis-estimate the actual total number of steals when the pool is * not quiescent. But the value is still useful for monitoring and * tuning fork/join programs: In general, steal counts should be * high enough to keep threads busy, but low enough to avoid * overhead and contention across threads. * @return the number of steals. */ public long getStealCount() { long sum = 0; ForkJoinWorkerThread[] ws = workers; for (int i = 0; i < ws.length; ++i) { ForkJoinWorkerThread t = ws[i]; if (t != null) sum += t.getWorkerStealCount(); } return sum; } /** * Returns the total number of tasks currently held in queues by * worker threads (but not including tasks submitted to the pool * that have not begun executing). This value is only an * approximation, obtained by iterating across all threads in the * pool. This method may be useful for tuning task granularities. * @return the number of tasks. */ public long getTotalPerThreadQueueSize() { long count = 0; ForkJoinWorkerThread[] ws = workers; for (int i = 0; i < ws.length; ++i) { ForkJoinWorkerThread t = ws[i]; if (t != null) count += t.getQueueSize(); } return count; } /** * Returns the number of tasks that have been submitted (via * <tt>submit</tt> or <tt>invoke</tt>) and are currently executing * in the pool. * @return the number of tasks. */ public int getActiveSubmissionCount() { return runningSubmissions.get(); } /** * Returns the factory used for constructing new workers * * @return the factory used for constructing new workers */ public ForkJoinWorkerThreadFactory getFactory() { return factory; } // Callbacks from submissions /** * Callback on starting execution of externally submitted job. */ final void submissionStarting() { runningSubmissions.incrementAndGet(); } /** * Completion callback from externally submitted job. */ final void submissionCompleted() { if (runningSubmissions.decrementAndGet() == 0 && runState.isAtLeastShutdown()) tryTerminateOnShutdown(); } /** * Wait for a pool event, if necessary. Called only by workers. */ final long barrierSync(long eventCount) { return poolBarrier.sync(eventCount); } /** * Embedded submission queue holds submissions not yet started by * workers. This is a variant of an Michael/Scott queue that * supports a fast check for apparent emptiness. This class * opportunistically subclasses AtromicReference for next-field */ static final class SQNode extends AtomicReference<SQNode> { Submission<?> submission; SQNode(Submission<?> s) { submission = s; } } /** * Quick check for likely non-emptiness. Returns true if an * add completed but not yet fully taken. */ final boolean mayHaveQueuedSubmissions() { return sqHead != sqTail; } /** * Returns true if there are any tasks submitted to this pool * that have not yet begun executing. * @return <tt>true</tt> if there are any queued submissions. */ public boolean hasQueuedSubmissions() { for (;;) { SQNode h = sqHead; SQNode t = sqTail; SQNode f = h.get(); if (h == sqHead) { if (f == null) return false; else if (h != t) return true; else casSqTail(t, f); } } } final void addSubmission(Submission<?> x) { SQNode n = new SQNode(x); for (;;) { SQNode t = sqTail; SQNode s = t.get(); if (t == sqTail) { if (s != null) casSqTail(t, s); else if (t.compareAndSet(s, n)) { casSqTail(t, n); return; } } } } final Submission<?> pollSubmission() { for (;;) { SQNode h = sqHead; SQNode t = sqTail; SQNode f = h.get(); if (h == sqHead) { if (f == null) return null; else if (h == t) casSqTail(t, f); else if (casSqHead(h, f)) { Submission<?> x = f.submission; f.submission = null; return x; } } } } // Temporary Unsafe mechanics for preliminary release static final Unsafe _unsafe; static final long activeCountOffset; static final long sqHeadOffset; static final long sqTailOffset; static { try { if (ForkJoinPool.class.getClassLoader() != null) { Field f = Unsafe.class.getDeclaredField("theUnsafe"); f.setAccessible(true); _unsafe = (Unsafe)f.get(null); } else _unsafe = Unsafe.getUnsafe(); activeCountOffset = _unsafe.objectFieldOffset (ForkJoinPool.class.getDeclaredField("activeCount")); sqHeadOffset = _unsafe.objectFieldOffset (ForkJoinPool.class.getDeclaredField("sqHead")); sqTailOffset = _unsafe.objectFieldOffset (ForkJoinPool.class.getDeclaredField("sqTail")); } catch (Exception e) { throw new RuntimeException("Could not initialize intrinsics", e); } } final boolean tryIncrementActiveCount() { int c = activeCount; return _unsafe.compareAndSwapInt(this, activeCountOffset, c, c+1); } final boolean tryDecrementActiveCount() { int c = activeCount; return _unsafe.compareAndSwapInt(this, activeCountOffset, c, c-1); } final void incrementActiveCount() { while (!tryIncrementActiveCount()) ; } final void decrementActiveCount() { while (!tryDecrementActiveCount()) ; } private boolean casSqTail(SQNode cmp, SQNode val) { return _unsafe.compareAndSwapObject(this, sqTailOffset, cmp, val); } private boolean casSqHead(SQNode cmp, SQNode val) { return _unsafe.compareAndSwapObject(this, sqHeadOffset, cmp, val); } }