├── .java-version ├── .gitignore ├── project ├── plugins.sbt └── build.properties ├── src └── main │ ├── scala │ └── monix │ │ └── forkJoin │ │ ├── AdaptedForkJoinTask.scala │ │ ├── AdaptedForkJoinPool.scala │ │ ├── StandardWorkerThreadFactory.scala │ │ ├── ForkJoinExecutionContext.scala │ │ └── DynamicWorkerThreadFactory.scala │ └── java │ └── monix │ └── forkJoin │ ├── Unsafe.java │ ├── package-info.java │ ├── RecursiveTask.java │ ├── ForkJoinWorkerThread.java │ ├── RecursiveAction.java │ ├── TransferQueue.java │ ├── ThreadLocalRandom.java │ ├── LinkedTransferQueue.java │ └── ForkJoinTask.java ├── LICENSE.txt └── README.md /.java-version: -------------------------------------------------------------------------------- 1 | 1.8 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea* 2 | *.log 3 | .DS_Store 4 | target/ 5 | /.lib/ 6 | project/target/ 7 | -------------------------------------------------------------------------------- /project/plugins.sbt: -------------------------------------------------------------------------------- 1 | resolvers += Classpaths.sbtPluginReleases 2 | 3 | addSbtPlugin("com.jsuereth" % "sbt-pgp" % "1.0.0") 4 | -------------------------------------------------------------------------------- /project/build.properties: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2012-2017 by its authors. Some rights reserved. 3 | # See the project homepage at: https://github.com/monix/monix-forkjoin 4 | # 5 | # Licensed under the MIT License (the "License"); you may not use this 6 | # file except in compliance with the License. You may obtain a copy 7 | # of the License at: 8 | # 9 | # https://github.com/monix/monix-forkjoin/blob/master/LICENSE.txt 10 | # 11 | 12 | sbt.version=0.13.13 13 | -------------------------------------------------------------------------------- /src/main/scala/monix/forkJoin/AdaptedForkJoinTask.scala: -------------------------------------------------------------------------------- 1 | package monix.forkJoin 2 | 3 | final class AdaptedForkJoinTask(runnable: Runnable) 4 | extends ForkJoinTask[Unit] { 5 | 6 | def setRawResult(u: Unit): Unit = () 7 | def getRawResult(): Unit = () 8 | 9 | def exec(): Boolean = 10 | try { runnable.run(); true } catch { 11 | case anything: Throwable => 12 | val t = Thread.currentThread 13 | t.getUncaughtExceptionHandler match { 14 | case null => 15 | case some => some.uncaughtException(t, anything) 16 | } 17 | throw anything 18 | } 19 | } -------------------------------------------------------------------------------- /src/main/scala/monix/forkJoin/AdaptedForkJoinPool.scala: -------------------------------------------------------------------------------- 1 | package monix.forkJoin 2 | 3 | import java.lang.Thread.UncaughtExceptionHandler 4 | import monix.forkJoin.ForkJoinPool.ForkJoinWorkerThreadFactory 5 | 6 | final class AdaptedForkJoinPool( 7 | parallelism: Int, 8 | factory: ForkJoinWorkerThreadFactory, 9 | handler: UncaughtExceptionHandler, 10 | asyncMode: Boolean) 11 | extends ForkJoinPool(parallelism, factory, handler, asyncMode) { 12 | 13 | override def execute(runnable: Runnable): Unit = { 14 | val fjt: ForkJoinTask[_] = runnable match { 15 | case t: ForkJoinTask[_] => t 16 | case r => new AdaptedForkJoinTask(r) 17 | } 18 | 19 | Thread.currentThread match { 20 | case fjw: ForkJoinWorkerThread if fjw.getPool eq this => fjt.fork() 21 | case _ => super.execute(fjt) 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/scala/monix/forkJoin/StandardWorkerThreadFactory.scala: -------------------------------------------------------------------------------- 1 | package monix.forkJoin 2 | 3 | import java.lang.Thread.UncaughtExceptionHandler 4 | import java.util.concurrent.ThreadFactory 5 | import monix.forkJoin.ForkJoinPool.ForkJoinWorkerThreadFactory 6 | 7 | final class StandardWorkerThreadFactory( 8 | prefix: String, 9 | reporter: Throwable => Unit, 10 | daemonic: Boolean) 11 | extends ThreadFactory with ForkJoinWorkerThreadFactory { 12 | 13 | def wire[T <: Thread](thread: T): T = { 14 | thread.setDaemon(daemonic) 15 | thread.setUncaughtExceptionHandler(new UncaughtExceptionHandler { 16 | override def uncaughtException(t: Thread, e: Throwable): Unit = 17 | reporter(e) 18 | }) 19 | 20 | thread.setName(prefix + "-" + thread.getId) 21 | thread 22 | } 23 | 24 | override def newThread(r: Runnable): Thread = 25 | wire(new Thread(r)) 26 | 27 | override def newThread(pool: ForkJoinPool): ForkJoinWorkerThread = 28 | wire(new ForkJoinWorkerThread(pool) {}) 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/monix/forkJoin/Unsafe.java: -------------------------------------------------------------------------------- 1 | /* __ *\ 2 | ** ________ ___ / / ___ Scala API ** 3 | ** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** 4 | ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** 5 | ** /____/\___/_/ |_/____/_/ | | ** 6 | ** |/ ** 7 | \* */ 8 | 9 | package monix.forkJoin; 10 | 11 | import java.lang.reflect.Field; 12 | 13 | public final class Unsafe { 14 | public final static sun.misc.Unsafe instance; 15 | static { 16 | try { 17 | sun.misc.Unsafe found = null; 18 | for(Field field : sun.misc.Unsafe.class.getDeclaredFields()) { 19 | if (field.getType() == sun.misc.Unsafe.class) { 20 | field.setAccessible(true); 21 | found = (sun.misc.Unsafe) field.get(null); 22 | break; 23 | } 24 | } 25 | if (found == null) throw new IllegalStateException("Can't find instance of sun.misc.Unsafe"); 26 | else instance = found; 27 | } catch(Throwable t) { 28 | throw new ExceptionInInitializerError(t); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/monix/forkJoin/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Written by Doug Lea with assistance from members of JCP JSR-166 3 | * Expert Group and released to the public domain, as explained at 4 | * http://creativecommons.org/publicdomain/zero/1.0/ 5 | */ 6 | 7 | 8 | /** 9 | * Preview versions of classes targeted for Java 7. Includes a 10 | * fine-grained parallel computation framework: ForkJoinTasks and 11 | * their related support classes provide a very efficient basis for 12 | * obtaining platform-independent parallel speed-ups of 13 | * computation-intensive operations. They are not a full substitute 14 | * for the kinds of arbitrary processing supported by Executors or 15 | * Threads. However, when applicable, they typically provide 16 | * significantly greater performance on multiprocessor platforms. 17 | * 18 | *

Candidates for fork/join processing mainly include those that 19 | * can be expressed using parallel divide-and-conquer techniques: To 20 | * solve a problem, break it in two (or more) parts, and then solve 21 | * those parts in parallel, continuing on in this way until the 22 | * problem is too small to be broken up, so is solved directly. The 23 | * underlying work-stealing framework makes subtasks 24 | * available to other threads (normally one per CPU), that help 25 | * complete the tasks. In general, the most efficient ForkJoinTasks 26 | * are those that directly implement this algorithmic design pattern. 27 | */ 28 | package monix.forkJoin; 29 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Scala is licensed under the BSD 3-Clause License. 2 | Scala License 3 | 4 | Copyright (c) 2002-2016 EPFL 5 | Copyright (c) 2011-2016 Lightbend, Inc. 6 | Copyright (c) 2016 Alexandru Nedelcu 7 | 8 | All rights reserved. 9 | 10 | Redistribution and use in source and binary forms, with or without modification, 11 | are permitted provided that the following conditions are met: 12 | 13 | - Redistributions of source code must retain the above copyright notice, 14 | this list of conditions and the following disclaimer. 15 | - Redistributions in binary form must reproduce the above copyright notice, 16 | this list of conditions and the following disclaimer in the documentation 17 | and/or other materials provided with the distribution. 18 | - Neither the name of the EPFL nor the names of its contributors may be 19 | used to endorse or promote products derived from this software without 20 | specific prior written permission. 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY 23 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 24 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 25 | SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 27 | OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | -------------------------------------------------------------------------------- /src/main/scala/monix/forkJoin/ForkJoinExecutionContext.scala: -------------------------------------------------------------------------------- 1 | package monix.forkJoin 2 | 3 | import java.lang.Thread.UncaughtExceptionHandler 4 | import scala.concurrent.ExecutionContext 5 | 6 | object ForkJoinExecutionContext { 7 | /** Creates a Scala `ExecutionContext` powered by a JSR-166 8 | * `ForkJoinPool` implementation with the ability to add threads 9 | * in case blocking operations happen. 10 | * 11 | * The resulting instance collaborates with Scala's `BlockContext` 12 | * and has the same behavior as Scala's own `global`. 13 | */ 14 | def createDynamic( 15 | parallelism: Int, 16 | maxThreads: Int, 17 | name: String = "forkJoin-dynamic", 18 | daemonic: Boolean = true, 19 | reporter: Throwable => Unit = _.printStackTrace()): ExecutionContext = { 20 | 21 | val exceptionHandler = new UncaughtExceptionHandler { 22 | def uncaughtException(t: Thread, e: Throwable) = 23 | reporter(e) 24 | } 25 | 26 | val pool = new AdaptedForkJoinPool( 27 | parallelism, 28 | new DynamicWorkerThreadFactory(name, maxThreads, exceptionHandler, daemonic), 29 | exceptionHandler, 30 | asyncMode = true 31 | ) 32 | 33 | ExecutionContext.fromExecutor(pool, reporter) 34 | } 35 | 36 | /** Creates a Scala `ExecutionContext` powered by a JSR-166 37 | * `ForkJoinPool` implementation. 38 | */ 39 | def createStandard( 40 | parallelism: Int, 41 | name: String = "forkJoin-standard", 42 | daemonic: Boolean = true, 43 | reporter: Throwable => Unit = _.printStackTrace()): ExecutionContext = { 44 | 45 | val exceptionHandler = new UncaughtExceptionHandler { 46 | def uncaughtException(t: Thread, e: Throwable) = 47 | reporter(e) 48 | } 49 | 50 | val pool = new AdaptedForkJoinPool( 51 | parallelism, 52 | new StandardWorkerThreadFactory(name, reporter, daemonic), 53 | exceptionHandler, 54 | asyncMode = true 55 | ) 56 | 57 | ExecutionContext.fromExecutor(pool, reporter) 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/monix/forkJoin/RecursiveTask.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Written by Doug Lea with assistance from members of JCP JSR-166 3 | * Expert Group and released to the public domain, as explained at 4 | * http://creativecommons.org/publicdomain/zero/1.0/ 5 | */ 6 | 7 | package monix.forkJoin; 8 | 9 | /** 10 | * A recursive result-bearing {@link ForkJoinTask}. 11 | * 12 | *

For a classic example, here is a task computing Fibonacci numbers: 13 | * 14 | *

 {@code
15 |  * class Fibonacci extends RecursiveTask {
16 |  *   final int n;
17 |  *   Fibonacci(int n) { this.n = n; }
18 |  *   Integer compute() {
19 |  *     if (n <= 1)
20 |  *        return n;
21 |  *     Fibonacci f1 = new Fibonacci(n - 1);
22 |  *     f1.fork();
23 |  *     Fibonacci f2 = new Fibonacci(n - 2);
24 |  *     return f2.compute() + f1.join();
25 |  *   }
26 |  * }}
27 | * 28 | * However, besides being a dumb way to compute Fibonacci functions 29 | * (there is a simple fast linear algorithm that you'd use in 30 | * practice), this is likely to perform poorly because the smallest 31 | * subtasks are too small to be worthwhile splitting up. Instead, as 32 | * is the case for nearly all fork/join applications, you'd pick some 33 | * minimum granularity size (for example 10 here) for which you always 34 | * sequentially solve rather than subdividing. 35 | * 36 | * @since 1.7 37 | * @author Doug Lea 38 | */ 39 | public abstract class RecursiveTask extends ForkJoinTask { 40 | private static final long serialVersionUID = 5232453952276485270L; 41 | 42 | /** 43 | * The result of the computation. 44 | */ 45 | V result; 46 | 47 | /** 48 | * The main computation performed by this task. 49 | */ 50 | protected abstract V compute(); 51 | 52 | public final V getRawResult() { 53 | return result; 54 | } 55 | 56 | protected final void setRawResult(V value) { 57 | result = value; 58 | } 59 | 60 | /** 61 | * Implements execution conventions for RecursiveTask. 62 | */ 63 | protected final boolean exec() { 64 | result = compute(); 65 | return true; 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # monix-forkjoin 2 | 3 | A port of the ForkJoinPool JSR-166 implementation used in Scala 2.11.x 4 | for usage in Scala 2.12. 5 | 6 | ## Rationale 7 | 8 | In Scala 2.11.8 the `scala.concurrent.forkjoin.ForkJoinPool` implementation 9 | is a fork of the JSR-166 implementation by Doug Lea, in order to provide 10 | support for Java versions older than version 8. 11 | However in Scala 2.12.x the implementation is now an alias for 12 | `java.util.concurrent.ForkJoinPool`, given of its availability in 13 | Java 8 and the Scala 2.12 requirement to have Java 8 as a target. 14 | 15 | Unfortunately these 2 implementations are NOT the same, as the 16 | old Scala 2.11 implementation has better throughput in testing. 17 | 18 | The version of `ForkJoinPool` in 2.11 uses busy-waiting more 19 | aggressively which helps out in tests with more cores than 20 | tasks. However, this comes at the expense of other workloads on 21 | the process/machine, especially because the JVM does not let the 22 | busy waiting signal its intention to the CPU with a Spin Loop hint. 23 | This trade-off was found during testing of the `ForkJoinPool` as it was 24 | integrated into parallel `java.util.stream` and is discussed in JDK-8080623. 25 | 26 | But in testing this implementation can have considerable better 27 | throughput and can prove useful for heavy CPU-bound tasks and 28 | the performance hit for some use-cases is quite noticeable. 29 | 30 | ## Usage 31 | 32 | Available for Scala 2.10, 2.11 and 2.12. 33 | Add the dependency in your SBT file: 34 | 35 | ```scala 36 | libraryDependencies += "io.monix" %% "monix-forkjoin" % "1.0" 37 | ``` 38 | 39 | And then: 40 | 41 | ```scala 42 | import monix.forkJoin.ForkJoinExecutionContext 43 | 44 | implicit val executionContext = 45 | ForkJoinExecutionContext.createDynamic( 46 | parallelism = Runtime.getRuntime.availableProcessors(), 47 | maxThreads = 256, 48 | name = "forkJoin-dynamic", 49 | daemonic = true 50 | ) 51 | ``` 52 | 53 | ## License 54 | 55 | The `monix-forkjoin` project is licensed under the 3-Clause BSD license, 56 | the same license as Scala, see `LICENSE.txt` for details. 57 | 58 | The `ForkJoinPool` implementation is copied from the Scala 2.11 repository, 59 | which itself was copied from Doug Lea's JSR-166 implementation and is under the 60 | [public domain](http://creativecommons.org/publicdomain/zero/1.0/). -------------------------------------------------------------------------------- /src/main/scala/monix/forkJoin/DynamicWorkerThreadFactory.scala: -------------------------------------------------------------------------------- 1 | package monix.forkJoin 2 | 3 | import java.util.concurrent.ThreadFactory 4 | import java.util.concurrent.atomic.AtomicInteger 5 | import monix.forkJoin.DynamicWorkerThreadFactory.EmptyBlockContext 6 | import monix.forkJoin.ForkJoinPool.{ForkJoinWorkerThreadFactory, ManagedBlocker} 7 | import scala.annotation.tailrec 8 | import scala.concurrent.{BlockContext, CanAwait} 9 | 10 | // Implement BlockContext on FJP threads 11 | final class DynamicWorkerThreadFactory( 12 | prefix: String, 13 | maxThreads: Int, 14 | uncaught: Thread.UncaughtExceptionHandler, 15 | daemonic: Boolean) 16 | extends ThreadFactory with ForkJoinWorkerThreadFactory { 17 | 18 | require(prefix ne null, "DefaultWorkerThreadFactory.prefix must be non null") 19 | require(maxThreads > 0, "DefaultWorkerThreadFactory.maxThreads must be greater than 0") 20 | 21 | private[this] val currentNumberOfThreads = new AtomicInteger(0) 22 | 23 | @tailrec private def reserveThread(): Boolean = 24 | currentNumberOfThreads.get match { 25 | case `maxThreads` | Int.`MaxValue` => false 26 | case other => currentNumberOfThreads.compareAndSet(other, other + 1) || reserveThread() 27 | } 28 | 29 | @tailrec private def deregisterThread(): Boolean = 30 | currentNumberOfThreads.get match { 31 | case 0 => false 32 | case other => currentNumberOfThreads.compareAndSet(other, other - 1) || deregisterThread() 33 | } 34 | 35 | def wire[T <: Thread](thread: T): T = { 36 | thread.setDaemon(daemonic) 37 | thread.setUncaughtExceptionHandler(uncaught) 38 | thread.setName(prefix + "-" + thread.getId) 39 | thread 40 | } 41 | 42 | // As per ThreadFactory contract newThread should return `null` if cannot create new thread. 43 | def newThread(runnable: Runnable): Thread = 44 | if (!reserveThread()) null else 45 | wire(new Thread(new Runnable { 46 | // We have to decrement the current thread count when the thread exits 47 | override def run() = 48 | try runnable.run() finally deregisterThread() 49 | })) 50 | 51 | def newThread(fjp: ForkJoinPool): ForkJoinWorkerThread = 52 | if (!reserveThread()) null else { 53 | wire(new ForkJoinWorkerThread(fjp) with BlockContext { 54 | // We have to decrement the current thread count when the thread exits 55 | final override def onTermination(exception: Throwable): Unit = 56 | deregisterThread() 57 | 58 | final override def blockOn[T](thunk: =>T)(implicit permission: CanAwait): T = { 59 | var result: T = null.asInstanceOf[T] 60 | ForkJoinPool.managedBlock(new ManagedBlocker { 61 | @volatile 62 | private[this] var isDone = false 63 | def isReleasable: Boolean = isDone 64 | 65 | def block(): Boolean = { 66 | result = try { 67 | // When we block, switch out the BlockContext temporarily so that nested 68 | // blocking does not created N new Threads 69 | BlockContext.withBlockContext(EmptyBlockContext) { thunk } 70 | } finally { 71 | isDone = true 72 | } 73 | true 74 | } 75 | }) 76 | 77 | result 78 | } 79 | }) 80 | } 81 | } 82 | 83 | object DynamicWorkerThreadFactory { 84 | /** Reusable instance that doesn't do anything special. */ 85 | private object EmptyBlockContext extends BlockContext { 86 | override def blockOn[T](thunk: => T)(implicit permission: CanAwait): T = 87 | thunk 88 | } 89 | } -------------------------------------------------------------------------------- /src/main/java/monix/forkJoin/ForkJoinWorkerThread.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Written by Doug Lea with assistance from members of JCP JSR-166 3 | * Expert Group and released to the public domain, as explained at 4 | * http://creativecommons.org/publicdomain/zero/1.0/ 5 | */ 6 | 7 | package monix.forkJoin; 8 | 9 | /** 10 | * A thread managed by a {@link ForkJoinPool}, which executes 11 | * {@link ForkJoinTask}s. 12 | * This class is subclassable solely for the sake of adding 13 | * functionality -- there are no overridable methods dealing with 14 | * scheduling or execution. However, you can override initialization 15 | * and termination methods surrounding the main task processing loop. 16 | * If you do create such a subclass, you will also need to supply a 17 | * custom {@link ForkJoinPool.ForkJoinWorkerThreadFactory} to use it 18 | * in a {@code ForkJoinPool}. 19 | * 20 | * @since 1.7 21 | * @author Doug Lea 22 | */ 23 | public class ForkJoinWorkerThread extends Thread { 24 | /* 25 | * ForkJoinWorkerThreads are managed by ForkJoinPools and perform 26 | * ForkJoinTasks. For explanation, see the internal documentation 27 | * of class ForkJoinPool. 28 | * 29 | * This class just maintains links to its pool and WorkQueue. The 30 | * pool field is set immediately upon construction, but the 31 | * workQueue field is not set until a call to registerWorker 32 | * completes. This leads to a visibility race, that is tolerated 33 | * by requiring that the workQueue field is only accessed by the 34 | * owning thread. 35 | */ 36 | 37 | final ForkJoinPool pool; // the pool this thread works in 38 | final ForkJoinPool.WorkQueue workQueue; // work-stealing mechanics 39 | 40 | /** 41 | * Creates a ForkJoinWorkerThread operating in the given pool. 42 | * 43 | * @param pool the pool this thread works in 44 | * @throws NullPointerException if pool is null 45 | */ 46 | protected ForkJoinWorkerThread(ForkJoinPool pool) { 47 | // Use a placeholder until a useful name can be set in registerWorker 48 | super("aForkJoinWorkerThread"); 49 | this.pool = pool; 50 | this.workQueue = pool.registerWorker(this); 51 | } 52 | 53 | /** 54 | * Returns the pool hosting this thread. 55 | * 56 | * @return the pool 57 | */ 58 | public ForkJoinPool getPool() { 59 | return pool; 60 | } 61 | 62 | /** 63 | * Returns the index number of this thread in its pool. The 64 | * returned value ranges from zero to the maximum number of 65 | * threads (minus one) that have ever been created in the pool. 66 | * This method may be useful for applications that track status or 67 | * collect results per-worker rather than per-task. 68 | * 69 | * @return the index number 70 | */ 71 | public int getPoolIndex() { 72 | return workQueue.poolIndex; 73 | } 74 | 75 | /** 76 | * Initializes internal state after construction but before 77 | * processing any tasks. If you override this method, you must 78 | * invoke {@code super.onStart()} at the beginning of the method. 79 | * Initialization requires care: Most fields must have legal 80 | * default values, to ensure that attempted accesses from other 81 | * threads work correctly even before this thread starts 82 | * processing tasks. 83 | */ 84 | protected void onStart() { 85 | } 86 | 87 | /** 88 | * Performs cleanup associated with termination of this worker 89 | * thread. If you override this method, you must invoke 90 | * {@code super.onTermination} at the end of the overridden method. 91 | * 92 | * @param exception the exception causing this thread to abort due 93 | * to an unrecoverable error, or {@code null} if completed normally 94 | */ 95 | protected void onTermination(Throwable exception) { 96 | } 97 | 98 | /** 99 | * This method is required to be public, but should never be 100 | * called explicitly. It performs the main run loop to execute 101 | * {@link ForkJoinTask}s. 102 | */ 103 | public void run() { 104 | Throwable exception = null; 105 | try { 106 | onStart(); 107 | pool.runWorker(workQueue); 108 | } catch (Throwable ex) { 109 | exception = ex; 110 | } finally { 111 | try { 112 | onTermination(exception); 113 | } catch (Throwable ex) { 114 | if (exception == null) 115 | exception = ex; 116 | } finally { 117 | pool.deregisterWorker(this, exception); 118 | } 119 | } 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /src/main/java/monix/forkJoin/RecursiveAction.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Written by Doug Lea with assistance from members of JCP JSR-166 3 | * Expert Group and released to the public domain, as explained at 4 | * http://creativecommons.org/publicdomain/zero/1.0/ 5 | */ 6 | 7 | package monix.forkJoin; 8 | 9 | /** 10 | * A recursive resultless {@link ForkJoinTask}. This class 11 | * establishes conventions to parameterize resultless actions as 12 | * {@code Void} {@code ForkJoinTask}s. Because {@code null} is the 13 | * only valid value of type {@code Void}, methods such as {@code join} 14 | * always return {@code null} upon completion. 15 | * 16 | *

Sample Usages. Here is a simple but complete ForkJoin 17 | * sort that sorts a given {@code long[]} array: 18 | * 19 | *

 {@code
 20 |  * static class SortTask extends RecursiveAction {
 21 |  *   final long[] array; final int lo, hi;
 22 |  *   SortTask(long[] array, int lo, int hi) {
 23 |  *     this.array = array; this.lo = lo; this.hi = hi;
 24 |  *   }
 25 |  *   SortTask(long[] array) { this(array, 0, array.length); }
 26 |  *   protected void compute() {
 27 |  *     if (hi - lo < THRESHOLD)
 28 |  *       sortSequentially(lo, hi);
 29 |  *     else {
 30 |  *       int mid = (lo + hi) >>> 1;
 31 |  *       invokeAll(new SortTask(array, lo, mid),
 32 |  *                 new SortTask(array, mid, hi));
 33 |  *       merge(lo, mid, hi);
 34 |  *     }
 35 |  *   }
 36 |  *   // implementation details follow:
 37 |  *   final static int THRESHOLD = 1000;
 38 |  *   void sortSequentially(int lo, int hi) {
 39 |  *     Arrays.sort(array, lo, hi);
 40 |  *   }
 41 |  *   void merge(int lo, int mid, int hi) {
 42 |  *     long[] buf = Arrays.copyOfRange(array, lo, mid);
 43 |  *     for (int i = 0, j = lo, k = mid; i < buf.length; j++)
 44 |  *       array[j] = (k == hi || buf[i] < array[k]) ?
 45 |  *         buf[i++] : array[k++];
 46 |  *   }
 47 |  * }}
48 | * 49 | * You could then sort {@code anArray} by creating {@code new 50 | * SortTask(anArray)} and invoking it in a ForkJoinPool. As a more 51 | * concrete simple example, the following task increments each element 52 | * of an array: 53 | *
 {@code
 54 |  * class IncrementTask extends RecursiveAction {
 55 |  *   final long[] array; final int lo, hi;
 56 |  *   IncrementTask(long[] array, int lo, int hi) {
 57 |  *     this.array = array; this.lo = lo; this.hi = hi;
 58 |  *   }
 59 |  *   protected void compute() {
 60 |  *     if (hi - lo < THRESHOLD) {
 61 |  *       for (int i = lo; i < hi; ++i)
 62 |  *         array[i]++;
 63 |  *     }
 64 |  *     else {
 65 |  *       int mid = (lo + hi) >>> 1;
 66 |  *       invokeAll(new IncrementTask(array, lo, mid),
 67 |  *                 new IncrementTask(array, mid, hi));
 68 |  *     }
 69 |  *   }
 70 |  * }}
71 | * 72 | *

The following example illustrates some refinements and idioms 73 | * that may lead to better performance: RecursiveActions need not be 74 | * fully recursive, so long as they maintain the basic 75 | * divide-and-conquer approach. Here is a class that sums the squares 76 | * of each element of a double array, by subdividing out only the 77 | * right-hand-sides of repeated divisions by two, and keeping track of 78 | * them with a chain of {@code next} references. It uses a dynamic 79 | * threshold based on method {@code getSurplusQueuedTaskCount}, but 80 | * counterbalances potential excess partitioning by directly 81 | * performing leaf actions on unstolen tasks rather than further 82 | * subdividing. 83 | * 84 | *

 {@code
 85 |  * double sumOfSquares(ForkJoinPool pool, double[] array) {
 86 |  *   int n = array.length;
 87 |  *   Applyer a = new Applyer(array, 0, n, null);
 88 |  *   pool.invoke(a);
 89 |  *   return a.result;
 90 |  * }
 91 |  *
 92 |  * class Applyer extends RecursiveAction {
 93 |  *   final double[] array;
 94 |  *   final int lo, hi;
 95 |  *   double result;
 96 |  *   Applyer next; // keeps track of right-hand-side tasks
 97 |  *   Applyer(double[] array, int lo, int hi, Applyer next) {
 98 |  *     this.array = array; this.lo = lo; this.hi = hi;
 99 |  *     this.next = next;
100 |  *   }
101 |  *
102 |  *   double atLeaf(int l, int h) {
103 |  *     double sum = 0;
104 |  *     for (int i = l; i < h; ++i) // perform leftmost base step
105 |  *       sum += array[i] * array[i];
106 |  *     return sum;
107 |  *   }
108 |  *
109 |  *   protected void compute() {
110 |  *     int l = lo;
111 |  *     int h = hi;
112 |  *     Applyer right = null;
113 |  *     while (h - l > 1 && getSurplusQueuedTaskCount() <= 3) {
114 |  *        int mid = (l + h) >>> 1;
115 |  *        right = new Applyer(array, mid, h, right);
116 |  *        right.fork();
117 |  *        h = mid;
118 |  *     }
119 |  *     double sum = atLeaf(l, h);
120 |  *     while (right != null) {
121 |  *        if (right.tryUnfork()) // directly calculate if not stolen
122 |  *          sum += right.atLeaf(right.lo, right.hi);
123 |  *       else {
124 |  *          right.join();
125 |  *          sum += right.result;
126 |  *        }
127 |  *        right = right.next;
128 |  *      }
129 |  *     result = sum;
130 |  *   }
131 |  * }}
132 | * 133 | * @since 1.7 134 | * @author Doug Lea 135 | */ 136 | public abstract class RecursiveAction extends ForkJoinTask { 137 | private static final long serialVersionUID = 5232453952276485070L; 138 | 139 | /** 140 | * The main computation performed by this task. 141 | */ 142 | protected abstract void compute(); 143 | 144 | /** 145 | * Always returns {@code null}. 146 | * 147 | * @return {@code null} always 148 | */ 149 | public final Void getRawResult() { return null; } 150 | 151 | /** 152 | * Requires null completion value. 153 | */ 154 | protected final void setRawResult(Void mustBeNull) { } 155 | 156 | /** 157 | * Implements execution conventions for RecursiveActions. 158 | */ 159 | protected final boolean exec() { 160 | compute(); 161 | return true; 162 | } 163 | 164 | } 165 | -------------------------------------------------------------------------------- /src/main/java/monix/forkJoin/TransferQueue.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Written by Doug Lea with assistance from members of JCP JSR-166 3 | * Expert Group and released to the public domain, as explained at 4 | * http://creativecommons.org/publicdomain/zero/1.0/ 5 | */ 6 | 7 | package monix.forkJoin; 8 | import java.util.concurrent.*; 9 | 10 | /** 11 | * A {@link BlockingQueue} in which producers may wait for consumers 12 | * to receive elements. A {@code TransferQueue} may be useful for 13 | * example in message passing applications in which producers 14 | * sometimes (using method {@link #transfer}) await receipt of 15 | * elements by consumers invoking {@code take} or {@code poll}, while 16 | * at other times enqueue elements (via method {@code put}) without 17 | * waiting for receipt. 18 | * {@linkplain #tryTransfer(Object) Non-blocking} and 19 | * {@linkplain #tryTransfer(Object,long,TimeUnit) time-out} versions of 20 | * {@code tryTransfer} are also available. 21 | * A {@code TransferQueue} may also be queried, via {@link 22 | * #hasWaitingConsumer}, whether there are any threads waiting for 23 | * items, which is a converse analogy to a {@code peek} operation. 24 | * 25 | *

Like other blocking queues, a {@code TransferQueue} may be 26 | * capacity bounded. If so, an attempted transfer operation may 27 | * initially block waiting for available space, and/or subsequently 28 | * block waiting for reception by a consumer. Note that in a queue 29 | * with zero capacity, such as {@link SynchronousQueue}, {@code put} 30 | * and {@code transfer} are effectively synonymous. 31 | * 32 | *

This interface is a member of the 33 | * 34 | * Java Collections Framework. 35 | * 36 | * @since 1.7 37 | * @author Doug Lea 38 | * @param the type of elements held in this collection 39 | */ 40 | public interface TransferQueue extends BlockingQueue { 41 | /** 42 | * Transfers the element to a waiting consumer immediately, if possible. 43 | * 44 | *

More precisely, transfers the specified element immediately 45 | * if there exists a consumer already waiting to receive it (in 46 | * {@link #take} or timed {@link #poll(long,TimeUnit) poll}), 47 | * otherwise returning {@code false} without enqueuing the element. 48 | * 49 | * @param e the element to transfer 50 | * @return {@code true} if the element was transferred, else 51 | * {@code false} 52 | * @throws ClassCastException if the class of the specified element 53 | * prevents it from being added to this queue 54 | * @throws NullPointerException if the specified element is null 55 | * @throws IllegalArgumentException if some property of the specified 56 | * element prevents it from being added to this queue 57 | */ 58 | boolean tryTransfer(E e); 59 | 60 | /** 61 | * Transfers the element to a consumer, waiting if necessary to do so. 62 | * 63 | *

More precisely, transfers the specified element immediately 64 | * if there exists a consumer already waiting to receive it (in 65 | * {@link #take} or timed {@link #poll(long,TimeUnit) poll}), 66 | * else waits until the element is received by a consumer. 67 | * 68 | * @param e the element to transfer 69 | * @throws InterruptedException if interrupted while waiting, 70 | * in which case the element is not left enqueued 71 | * @throws ClassCastException if the class of the specified element 72 | * prevents it from being added to this queue 73 | * @throws NullPointerException if the specified element is null 74 | * @throws IllegalArgumentException if some property of the specified 75 | * element prevents it from being added to this queue 76 | */ 77 | void transfer(E e) throws InterruptedException; 78 | 79 | /** 80 | * Transfers the element to a consumer if it is possible to do so 81 | * before the timeout elapses. 82 | * 83 | *

More precisely, transfers the specified element immediately 84 | * if there exists a consumer already waiting to receive it (in 85 | * {@link #take} or timed {@link #poll(long,TimeUnit) poll}), 86 | * else waits until the element is received by a consumer, 87 | * returning {@code false} if the specified wait time elapses 88 | * before the element can be transferred. 89 | * 90 | * @param e the element to transfer 91 | * @param timeout how long to wait before giving up, in units of 92 | * {@code unit} 93 | * @param unit a {@code TimeUnit} determining how to interpret the 94 | * {@code timeout} parameter 95 | * @return {@code true} if successful, or {@code false} if 96 | * the specified waiting time elapses before completion, 97 | * in which case the element is not left enqueued 98 | * @throws InterruptedException if interrupted while waiting, 99 | * in which case the element is not left enqueued 100 | * @throws ClassCastException if the class of the specified element 101 | * prevents it from being added to this queue 102 | * @throws NullPointerException if the specified element is null 103 | * @throws IllegalArgumentException if some property of the specified 104 | * element prevents it from being added to this queue 105 | */ 106 | boolean tryTransfer(E e, long timeout, TimeUnit unit) 107 | throws InterruptedException; 108 | 109 | /** 110 | * Returns {@code true} if there is at least one consumer waiting 111 | * to receive an element via {@link #take} or 112 | * timed {@link #poll(long,TimeUnit) poll}. 113 | * The return value represents a momentary state of affairs. 114 | * 115 | * @return {@code true} if there is at least one waiting consumer 116 | */ 117 | boolean hasWaitingConsumer(); 118 | 119 | /** 120 | * Returns an estimate of the number of consumers waiting to 121 | * receive elements via {@link #take} or timed 122 | * {@link #poll(long,TimeUnit) poll}. The return value is an 123 | * approximation of a momentary state of affairs, that may be 124 | * inaccurate if consumers have completed or given up waiting. 125 | * The value may be useful for monitoring and heuristics, but 126 | * not for synchronization control. Implementations of this 127 | * method are likely to be noticeably slower than those for 128 | * {@link #hasWaitingConsumer}. 129 | * 130 | * @return the number of consumers waiting to receive elements 131 | */ 132 | int getWaitingConsumerCount(); 133 | } 134 | -------------------------------------------------------------------------------- /src/main/java/monix/forkJoin/ThreadLocalRandom.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Written by Doug Lea with assistance from members of JCP JSR-166 3 | * Expert Group and released to the public domain, as explained at 4 | * http://creativecommons.org/publicdomain/zero/1.0/ 5 | */ 6 | 7 | package monix.forkJoin; 8 | 9 | import java.util.Random; 10 | 11 | /** 12 | * A random number generator isolated to the current thread. Like the 13 | * global {@link java.util.Random} generator used by the {@link 14 | * java.lang.Math} class, a {@code ThreadLocalRandom} is initialized 15 | * with an internally generated seed that may not otherwise be 16 | * modified. When applicable, use of {@code ThreadLocalRandom} rather 17 | * than shared {@code Random} objects in concurrent programs will 18 | * typically encounter much less overhead and contention. Use of 19 | * {@code ThreadLocalRandom} is particularly appropriate when multiple 20 | * tasks (for example, each a {@link ForkJoinTask}) use random numbers 21 | * in parallel in thread pools. 22 | * 23 | *

Usages of this class should typically be of the form: 24 | * {@code ThreadLocalRandom.current().nextX(...)} (where 25 | * {@code X} is {@code Int}, {@code Long}, etc). 26 | * When all usages are of this form, it is never possible to 27 | * accidentally share a {@code ThreadLocalRandom} across multiple threads. 28 | * 29 | *

This class also provides additional commonly used bounded random 30 | * generation methods. 31 | * 32 | * @since 1.7 33 | * @author Doug Lea 34 | */ 35 | public class ThreadLocalRandom extends Random { 36 | // same constants as Random, but must be redeclared because private 37 | private static final long multiplier = 0x5DEECE66DL; 38 | private static final long addend = 0xBL; 39 | private static final long mask = (1L << 48) - 1; 40 | 41 | /** 42 | * The random seed. We can't use super.seed. 43 | */ 44 | private long rnd; 45 | 46 | /** 47 | * Initialization flag to permit calls to setSeed to succeed only 48 | * while executing the Random constructor. We can't allow others 49 | * since it would cause setting seed in one part of a program to 50 | * unintentionally impact other usages by the thread. 51 | */ 52 | boolean initialized; 53 | 54 | // Padding to help avoid memory contention among seed updates in 55 | // different TLRs in the common case that they are located near 56 | // each other. 57 | private long pad0, pad1, pad2, pad3, pad4, pad5, pad6, pad7; 58 | 59 | /** 60 | * The actual ThreadLocal 61 | */ 62 | private static final ThreadLocal localRandom = 63 | new ThreadLocal() { 64 | protected ThreadLocalRandom initialValue() { 65 | return new ThreadLocalRandom(); 66 | } 67 | }; 68 | 69 | 70 | /** 71 | * Constructor called only by localRandom.initialValue. 72 | */ 73 | ThreadLocalRandom() { 74 | super(); 75 | initialized = true; 76 | } 77 | 78 | /** 79 | * Returns the current thread's {@code ThreadLocalRandom}. 80 | * 81 | * @return the current thread's {@code ThreadLocalRandom} 82 | */ 83 | public static ThreadLocalRandom current() { 84 | return localRandom.get(); 85 | } 86 | 87 | /** 88 | * Throws {@code UnsupportedOperationException}. Setting seeds in 89 | * this generator is not supported. 90 | * 91 | * @throws UnsupportedOperationException always 92 | */ 93 | public void setSeed(long seed) { 94 | if (initialized) 95 | throw new UnsupportedOperationException(); 96 | rnd = (seed ^ multiplier) & mask; 97 | } 98 | 99 | protected int next(int bits) { 100 | rnd = (rnd * multiplier + addend) & mask; 101 | return (int) (rnd >>> (48-bits)); 102 | } 103 | 104 | /** 105 | * Returns a pseudorandom, uniformly distributed value between the 106 | * given least value (inclusive) and bound (exclusive). 107 | * 108 | * @param least the least value returned 109 | * @param bound the upper bound (exclusive) 110 | * @throws IllegalArgumentException if least greater than or equal 111 | * to bound 112 | * @return the next value 113 | */ 114 | public int nextInt(int least, int bound) { 115 | if (least >= bound) 116 | throw new IllegalArgumentException(); 117 | return nextInt(bound - least) + least; 118 | } 119 | 120 | /** 121 | * Returns a pseudorandom, uniformly distributed value 122 | * between 0 (inclusive) and the specified value (exclusive). 123 | * 124 | * @param n the bound on the random number to be returned. Must be 125 | * positive. 126 | * @return the next value 127 | * @throws IllegalArgumentException if n is not positive 128 | */ 129 | public long nextLong(long n) { 130 | if (n <= 0) 131 | throw new IllegalArgumentException("n must be positive"); 132 | // Divide n by two until small enough for nextInt. On each 133 | // iteration (at most 31 of them but usually much less), 134 | // randomly choose both whether to include high bit in result 135 | // (offset) and whether to continue with the lower vs upper 136 | // half (which makes a difference only if odd). 137 | long offset = 0; 138 | while (n >= Integer.MAX_VALUE) { 139 | int bits = next(2); 140 | long half = n >>> 1; 141 | long nextn = ((bits & 2) == 0) ? half : n - half; 142 | if ((bits & 1) == 0) 143 | offset += n - nextn; 144 | n = nextn; 145 | } 146 | return offset + nextInt((int) n); 147 | } 148 | 149 | /** 150 | * Returns a pseudorandom, uniformly distributed value between the 151 | * given least value (inclusive) and bound (exclusive). 152 | * 153 | * @param least the least value returned 154 | * @param bound the upper bound (exclusive) 155 | * @return the next value 156 | * @throws IllegalArgumentException if least greater than or equal 157 | * to bound 158 | */ 159 | public long nextLong(long least, long bound) { 160 | if (least >= bound) 161 | throw new IllegalArgumentException(); 162 | return nextLong(bound - least) + least; 163 | } 164 | 165 | /** 166 | * Returns a pseudorandom, uniformly distributed {@code double} value 167 | * between 0 (inclusive) and the specified value (exclusive). 168 | * 169 | * @param n the bound on the random number to be returned. Must be 170 | * positive. 171 | * @return the next value 172 | * @throws IllegalArgumentException if n is not positive 173 | */ 174 | public double nextDouble(double n) { 175 | if (n <= 0) 176 | throw new IllegalArgumentException("n must be positive"); 177 | return nextDouble() * n; 178 | } 179 | 180 | /** 181 | * Returns a pseudorandom, uniformly distributed value between the 182 | * given least value (inclusive) and bound (exclusive). 183 | * 184 | * @param least the least value returned 185 | * @param bound the upper bound (exclusive) 186 | * @return the next value 187 | * @throws IllegalArgumentException if least greater than or equal 188 | * to bound 189 | */ 190 | public double nextDouble(double least, double bound) { 191 | if (least >= bound) 192 | throw new IllegalArgumentException(); 193 | return nextDouble() * (bound - least) + least; 194 | } 195 | 196 | private static final long serialVersionUID = -5851777807851030925L; 197 | } 198 | -------------------------------------------------------------------------------- /src/main/java/monix/forkJoin/LinkedTransferQueue.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Written by Doug Lea with assistance from members of JCP JSR-166 3 | * Expert Group and released to the public domain, as explained at 4 | * http://creativecommons.org/publicdomain/zero/1.0/ 5 | */ 6 | 7 | package monix.forkJoin; 8 | 9 | import java.util.AbstractQueue; 10 | import java.util.Collection; 11 | import java.util.Iterator; 12 | import java.util.NoSuchElementException; 13 | import java.util.Queue; 14 | import java.util.concurrent.TimeUnit; 15 | import java.util.concurrent.locks.LockSupport; 16 | 17 | /** 18 | * An unbounded {@link TransferQueue} based on linked nodes. 19 | * This queue orders elements FIFO (first-in-first-out) with respect 20 | * to any given producer. The head of the queue is that 21 | * element that has been on the queue the longest time for some 22 | * producer. The tail of the queue is that element that has 23 | * been on the queue the shortest time for some producer. 24 | * 25 | *

Beware that, unlike in most collections, the {@code size} method 26 | * is NOT a constant-time operation. Because of the 27 | * asynchronous nature of these queues, determining the current number 28 | * of elements requires a traversal of the elements, and so may report 29 | * inaccurate results if this collection is modified during traversal. 30 | * Additionally, the bulk operations {@code addAll}, 31 | * {@code removeAll}, {@code retainAll}, {@code containsAll}, 32 | * {@code equals}, and {@code toArray} are not guaranteed 33 | * to be performed atomically. For example, an iterator operating 34 | * concurrently with an {@code addAll} operation might view only some 35 | * of the added elements. 36 | * 37 | *

This class and its iterator implement all of the 38 | * optional methods of the {@link Collection} and {@link 39 | * Iterator} interfaces. 40 | * 41 | *

Memory consistency effects: As with other concurrent 42 | * collections, actions in a thread prior to placing an object into a 43 | * {@code LinkedTransferQueue} 44 | * happen-before 45 | * actions subsequent to the access or removal of that element from 46 | * the {@code LinkedTransferQueue} in another thread. 47 | * 48 | *

This class is a member of the 49 | * 50 | * Java Collections Framework. 51 | * 52 | * @since 1.7 53 | * @author Doug Lea 54 | * @param the type of elements held in this collection 55 | */ 56 | public class LinkedTransferQueue extends AbstractQueue 57 | implements TransferQueue, java.io.Serializable { 58 | private static final long serialVersionUID = -3223113410248163686L; 59 | 60 | /* 61 | * *** Overview of Dual Queues with Slack *** 62 | * 63 | * Dual Queues, introduced by Scherer and Scott 64 | * (http://www.cs.rice.edu/~wns1/papers/2004-DISC-DDS.pdf) are 65 | * (linked) queues in which nodes may represent either data or 66 | * requests. When a thread tries to enqueue a data node, but 67 | * encounters a request node, it instead "matches" and removes it; 68 | * and vice versa for enqueuing requests. Blocking Dual Queues 69 | * arrange that threads enqueuing unmatched requests block until 70 | * other threads provide the match. Dual Synchronous Queues (see 71 | * Scherer, Lea, & Scott 72 | * http://www.cs.rochester.edu/u/scott/papers/2009_Scherer_CACM_SSQ.pdf) 73 | * additionally arrange that threads enqueuing unmatched data also 74 | * block. Dual Transfer Queues support all of these modes, as 75 | * dictated by callers. 76 | * 77 | * A FIFO dual queue may be implemented using a variation of the 78 | * Michael & Scott (M&S) lock-free queue algorithm 79 | * (http://www.cs.rochester.edu/u/scott/papers/1996_PODC_queues.pdf). 80 | * It maintains two pointer fields, "head", pointing to a 81 | * (matched) node that in turn points to the first actual 82 | * (unmatched) queue node (or null if empty); and "tail" that 83 | * points to the last node on the queue (or again null if 84 | * empty). For example, here is a possible queue with four data 85 | * elements: 86 | * 87 | * head tail 88 | * | | 89 | * v v 90 | * M -> U -> U -> U -> U 91 | * 92 | * The M&S queue algorithm is known to be prone to scalability and 93 | * overhead limitations when maintaining (via CAS) these head and 94 | * tail pointers. This has led to the development of 95 | * contention-reducing variants such as elimination arrays (see 96 | * Moir et al http://portal.acm.org/citation.cfm?id=1074013) and 97 | * optimistic back pointers (see Ladan-Mozes & Shavit 98 | * http://people.csail.mit.edu/edya/publications/OptimisticFIFOQueue-journal.pdf). 99 | * However, the nature of dual queues enables a simpler tactic for 100 | * improving M&S-style implementations when dual-ness is needed. 101 | * 102 | * In a dual queue, each node must atomically maintain its match 103 | * status. While there are other possible variants, we implement 104 | * this here as: for a data-mode node, matching entails CASing an 105 | * "item" field from a non-null data value to null upon match, and 106 | * vice-versa for request nodes, CASing from null to a data 107 | * value. (Note that the linearization properties of this style of 108 | * queue are easy to verify -- elements are made available by 109 | * linking, and unavailable by matching.) Compared to plain M&S 110 | * queues, this property of dual queues requires one additional 111 | * successful atomic operation per enq/deq pair. But it also 112 | * enables lower cost variants of queue maintenance mechanics. (A 113 | * variation of this idea applies even for non-dual queues that 114 | * support deletion of interior elements, such as 115 | * j.u.c.ConcurrentLinkedQueue.) 116 | * 117 | * Once a node is matched, its match status can never again 118 | * change. We may thus arrange that the linked list of them 119 | * contain a prefix of zero or more matched nodes, followed by a 120 | * suffix of zero or more unmatched nodes. (Note that we allow 121 | * both the prefix and suffix to be zero length, which in turn 122 | * means that we do not use a dummy header.) If we were not 123 | * concerned with either time or space efficiency, we could 124 | * correctly perform enqueue and dequeue operations by traversing 125 | * from a pointer to the initial node; CASing the item of the 126 | * first unmatched node on match and CASing the next field of the 127 | * trailing node on appends. (Plus some special-casing when 128 | * initially empty). While this would be a terrible idea in 129 | * itself, it does have the benefit of not requiring ANY atomic 130 | * updates on head/tail fields. 131 | * 132 | * We introduce here an approach that lies between the extremes of 133 | * never versus always updating queue (head and tail) pointers. 134 | * This offers a tradeoff between sometimes requiring extra 135 | * traversal steps to locate the first and/or last unmatched 136 | * nodes, versus the reduced overhead and contention of fewer 137 | * updates to queue pointers. For example, a possible snapshot of 138 | * a queue is: 139 | * 140 | * head tail 141 | * | | 142 | * v v 143 | * M -> M -> U -> U -> U -> U 144 | * 145 | * The best value for this "slack" (the targeted maximum distance 146 | * between the value of "head" and the first unmatched node, and 147 | * similarly for "tail") is an empirical matter. We have found 148 | * that using very small constants in the range of 1-3 work best 149 | * over a range of platforms. Larger values introduce increasing 150 | * costs of cache misses and risks of long traversal chains, while 151 | * smaller values increase CAS contention and overhead. 152 | * 153 | * Dual queues with slack differ from plain M&S dual queues by 154 | * virtue of only sometimes updating head or tail pointers when 155 | * matching, appending, or even traversing nodes; in order to 156 | * maintain a targeted slack. The idea of "sometimes" may be 157 | * operationalized in several ways. The simplest is to use a 158 | * per-operation counter incremented on each traversal step, and 159 | * to try (via CAS) to update the associated queue pointer 160 | * whenever the count exceeds a threshold. Another, that requires 161 | * more overhead, is to use random number generators to update 162 | * with a given probability per traversal step. 163 | * 164 | * In any strategy along these lines, because CASes updating 165 | * fields may fail, the actual slack may exceed targeted 166 | * slack. However, they may be retried at any time to maintain 167 | * targets. Even when using very small slack values, this 168 | * approach works well for dual queues because it allows all 169 | * operations up to the point of matching or appending an item 170 | * (hence potentially allowing progress by another thread) to be 171 | * read-only, thus not introducing any further contention. As 172 | * described below, we implement this by performing slack 173 | * maintenance retries only after these points. 174 | * 175 | * As an accompaniment to such techniques, traversal overhead can 176 | * be further reduced without increasing contention of head 177 | * pointer updates: Threads may sometimes shortcut the "next" link 178 | * path from the current "head" node to be closer to the currently 179 | * known first unmatched node, and similarly for tail. Again, this 180 | * may be triggered with using thresholds or randomization. 181 | * 182 | * These ideas must be further extended to avoid unbounded amounts 183 | * of costly-to-reclaim garbage caused by the sequential "next" 184 | * links of nodes starting at old forgotten head nodes: As first 185 | * described in detail by Boehm 186 | * (http://portal.acm.org/citation.cfm?doid=503272.503282) if a GC 187 | * delays noticing that any arbitrarily old node has become 188 | * garbage, all newer dead nodes will also be unreclaimed. 189 | * (Similar issues arise in non-GC environments.) To cope with 190 | * this in our implementation, upon CASing to advance the head 191 | * pointer, we set the "next" link of the previous head to point 192 | * only to itself; thus limiting the length of connected dead lists. 193 | * (We also take similar care to wipe out possibly garbage 194 | * retaining values held in other Node fields.) However, doing so 195 | * adds some further complexity to traversal: If any "next" 196 | * pointer links to itself, it indicates that the current thread 197 | * has lagged behind a head-update, and so the traversal must 198 | * continue from the "head". Traversals trying to find the 199 | * current tail starting from "tail" may also encounter 200 | * self-links, in which case they also continue at "head". 201 | * 202 | * It is tempting in slack-based scheme to not even use CAS for 203 | * updates (similarly to Ladan-Mozes & Shavit). However, this 204 | * cannot be done for head updates under the above link-forgetting 205 | * mechanics because an update may leave head at a detached node. 206 | * And while direct writes are possible for tail updates, they 207 | * increase the risk of long retraversals, and hence long garbage 208 | * chains, which can be much more costly than is worthwhile 209 | * considering that the cost difference of performing a CAS vs 210 | * write is smaller when they are not triggered on each operation 211 | * (especially considering that writes and CASes equally require 212 | * additional GC bookkeeping ("write barriers") that are sometimes 213 | * more costly than the writes themselves because of contention). 214 | * 215 | * *** Overview of implementation *** 216 | * 217 | * We use a threshold-based approach to updates, with a slack 218 | * threshold of two -- that is, we update head/tail when the 219 | * current pointer appears to be two or more steps away from the 220 | * first/last node. The slack value is hard-wired: a path greater 221 | * than one is naturally implemented by checking equality of 222 | * traversal pointers except when the list has only one element, 223 | * in which case we keep slack threshold at one. Avoiding tracking 224 | * explicit counts across method calls slightly simplifies an 225 | * already-messy implementation. Using randomization would 226 | * probably work better if there were a low-quality dirt-cheap 227 | * per-thread one available, but even ThreadLocalRandom is too 228 | * heavy for these purposes. 229 | * 230 | * With such a small slack threshold value, it is not worthwhile 231 | * to augment this with path short-circuiting (i.e., unsplicing 232 | * interior nodes) except in the case of cancellation/removal (see 233 | * below). 234 | * 235 | * We allow both the head and tail fields to be null before any 236 | * nodes are enqueued; initializing upon first append. This 237 | * simplifies some other logic, as well as providing more 238 | * efficient explicit control paths instead of letting JVMs insert 239 | * implicit NullPointerExceptions when they are null. While not 240 | * currently fully implemented, we also leave open the possibility 241 | * of re-nulling these fields when empty (which is complicated to 242 | * arrange, for little benefit.) 243 | * 244 | * All enqueue/dequeue operations are handled by the single method 245 | * "xfer" with parameters indicating whether to act as some form 246 | * of offer, put, poll, take, or transfer (each possibly with 247 | * timeout). The relative complexity of using one monolithic 248 | * method outweighs the code bulk and maintenance problems of 249 | * using separate methods for each case. 250 | * 251 | * Operation consists of up to three phases. The first is 252 | * implemented within method xfer, the second in tryAppend, and 253 | * the third in method awaitMatch. 254 | * 255 | * 1. Try to match an existing node 256 | * 257 | * Starting at head, skip already-matched nodes until finding 258 | * an unmatched node of opposite mode, if one exists, in which 259 | * case matching it and returning, also if necessary updating 260 | * head to one past the matched node (or the node itself if the 261 | * list has no other unmatched nodes). If the CAS misses, then 262 | * a loop retries advancing head by two steps until either 263 | * success or the slack is at most two. By requiring that each 264 | * attempt advances head by two (if applicable), we ensure that 265 | * the slack does not grow without bound. Traversals also check 266 | * if the initial head is now off-list, in which case they 267 | * start at the new head. 268 | * 269 | * If no candidates are found and the call was untimed 270 | * poll/offer, (argument "how" is NOW) return. 271 | * 272 | * 2. Try to append a new node (method tryAppend) 273 | * 274 | * Starting at current tail pointer, find the actual last node 275 | * and try to append a new node (or if head was null, establish 276 | * the first node). Nodes can be appended only if their 277 | * predecessors are either already matched or are of the same 278 | * mode. If we detect otherwise, then a new node with opposite 279 | * mode must have been appended during traversal, so we must 280 | * restart at phase 1. The traversal and update steps are 281 | * otherwise similar to phase 1: Retrying upon CAS misses and 282 | * checking for staleness. In particular, if a self-link is 283 | * encountered, then we can safely jump to a node on the list 284 | * by continuing the traversal at current head. 285 | * 286 | * On successful append, if the call was ASYNC, return. 287 | * 288 | * 3. Await match or cancellation (method awaitMatch) 289 | * 290 | * Wait for another thread to match node; instead cancelling if 291 | * the current thread was interrupted or the wait timed out. On 292 | * multiprocessors, we use front-of-queue spinning: If a node 293 | * appears to be the first unmatched node in the queue, it 294 | * spins a bit before blocking. In either case, before blocking 295 | * it tries to unsplice any nodes between the current "head" 296 | * and the first unmatched node. 297 | * 298 | * Front-of-queue spinning vastly improves performance of 299 | * heavily contended queues. And so long as it is relatively 300 | * brief and "quiet", spinning does not much impact performance 301 | * of less-contended queues. During spins threads check their 302 | * interrupt status and generate a thread-local random number 303 | * to decide to occasionally perform a Thread.yield. While 304 | * yield has underdefined specs, we assume that it might help, 305 | * and will not hurt, in limiting impact of spinning on busy 306 | * systems. We also use smaller (1/2) spins for nodes that are 307 | * not known to be front but whose predecessors have not 308 | * blocked -- these "chained" spins avoid artifacts of 309 | * front-of-queue rules which otherwise lead to alternating 310 | * nodes spinning vs blocking. Further, front threads that 311 | * represent phase changes (from data to request node or vice 312 | * versa) compared to their predecessors receive additional 313 | * chained spins, reflecting longer paths typically required to 314 | * unblock threads during phase changes. 315 | * 316 | * 317 | * ** Unlinking removed interior nodes ** 318 | * 319 | * In addition to minimizing garbage retention via self-linking 320 | * described above, we also unlink removed interior nodes. These 321 | * may arise due to timed out or interrupted waits, or calls to 322 | * remove(x) or Iterator.remove. Normally, given a node that was 323 | * at one time known to be the predecessor of some node s that is 324 | * to be removed, we can unsplice s by CASing the next field of 325 | * its predecessor if it still points to s (otherwise s must 326 | * already have been removed or is now offlist). But there are two 327 | * situations in which we cannot guarantee to make node s 328 | * unreachable in this way: (1) If s is the trailing node of list 329 | * (i.e., with null next), then it is pinned as the target node 330 | * for appends, so can only be removed later after other nodes are 331 | * appended. (2) We cannot necessarily unlink s given a 332 | * predecessor node that is matched (including the case of being 333 | * cancelled): the predecessor may already be unspliced, in which 334 | * case some previous reachable node may still point to s. 335 | * (For further explanation see Herlihy & Shavit "The Art of 336 | * Multiprocessor Programming" chapter 9). Although, in both 337 | * cases, we can rule out the need for further action if either s 338 | * or its predecessor are (or can be made to be) at, or fall off 339 | * from, the head of list. 340 | * 341 | * Without taking these into account, it would be possible for an 342 | * unbounded number of supposedly removed nodes to remain 343 | * reachable. Situations leading to such buildup are uncommon but 344 | * can occur in practice; for example when a series of short timed 345 | * calls to poll repeatedly time out but never otherwise fall off 346 | * the list because of an untimed call to take at the front of the 347 | * queue. 348 | * 349 | * When these cases arise, rather than always retraversing the 350 | * entire list to find an actual predecessor to unlink (which 351 | * won't help for case (1) anyway), we record a conservative 352 | * estimate of possible unsplice failures (in "sweepVotes"). 353 | * We trigger a full sweep when the estimate exceeds a threshold 354 | * ("SWEEP_THRESHOLD") indicating the maximum number of estimated 355 | * removal failures to tolerate before sweeping through, unlinking 356 | * cancelled nodes that were not unlinked upon initial removal. 357 | * We perform sweeps by the thread hitting threshold (rather than 358 | * background threads or by spreading work to other threads) 359 | * because in the main contexts in which removal occurs, the 360 | * caller is already timed-out, cancelled, or performing a 361 | * potentially O(n) operation (e.g. remove(x)), none of which are 362 | * time-critical enough to warrant the overhead that alternatives 363 | * would impose on other threads. 364 | * 365 | * Because the sweepVotes estimate is conservative, and because 366 | * nodes become unlinked "naturally" as they fall off the head of 367 | * the queue, and because we allow votes to accumulate even while 368 | * sweeps are in progress, there are typically significantly fewer 369 | * such nodes than estimated. Choice of a threshold value 370 | * balances the likelihood of wasted effort and contention, versus 371 | * providing a worst-case bound on retention of interior nodes in 372 | * quiescent queues. The value defined below was chosen 373 | * empirically to balance these under various timeout scenarios. 374 | * 375 | * Note that we cannot self-link unlinked interior nodes during 376 | * sweeps. However, the associated garbage chains terminate when 377 | * some successor ultimately falls off the head of the list and is 378 | * self-linked. 379 | */ 380 | 381 | /** True if on multiprocessor */ 382 | private static final boolean MP = 383 | Runtime.getRuntime().availableProcessors() > 1; 384 | 385 | /** 386 | * The number of times to spin (with randomly interspersed calls 387 | * to Thread.yield) on multiprocessor before blocking when a node 388 | * is apparently the first waiter in the queue. See above for 389 | * explanation. Must be a power of two. The value is empirically 390 | * derived -- it works pretty well across a variety of processors, 391 | * numbers of CPUs, and OSes. 392 | */ 393 | private static final int FRONT_SPINS = 1 << 7; 394 | 395 | /** 396 | * The number of times to spin before blocking when a node is 397 | * preceded by another node that is apparently spinning. Also 398 | * serves as an increment to FRONT_SPINS on phase changes, and as 399 | * base average frequency for yielding during spins. Must be a 400 | * power of two. 401 | */ 402 | private static final int CHAINED_SPINS = FRONT_SPINS >>> 1; 403 | 404 | /** 405 | * The maximum number of estimated removal failures (sweepVotes) 406 | * to tolerate before sweeping through the queue unlinking 407 | * cancelled nodes that were not unlinked upon initial 408 | * removal. See above for explanation. The value must be at least 409 | * two to avoid useless sweeps when removing trailing nodes. 410 | */ 411 | static final int SWEEP_THRESHOLD = 32; 412 | 413 | /** 414 | * Queue nodes. Uses Object, not E, for items to allow forgetting 415 | * them after use. Relies heavily on Unsafe mechanics to minimize 416 | * unnecessary ordering constraints: Writes that are intrinsically 417 | * ordered wrt other accesses or CASes use simple relaxed forms. 418 | */ 419 | static final class Node { 420 | final boolean isData; // false if this is a request node 421 | volatile Object item; // initially non-null if isData; CASed to match 422 | volatile Node next; 423 | volatile Thread waiter; // null until waiting 424 | 425 | // CAS methods for fields 426 | final boolean casNext(Node cmp, Node val) { 427 | return UNSAFE.compareAndSwapObject(this, nextOffset, cmp, val); 428 | } 429 | 430 | final boolean casItem(Object cmp, Object val) { 431 | // assert cmp == null || cmp.getClass() != Node.class; 432 | return UNSAFE.compareAndSwapObject(this, itemOffset, cmp, val); 433 | } 434 | 435 | /** 436 | * Constructs a new node. Uses relaxed write because item can 437 | * only be seen after publication via casNext. 438 | */ 439 | Node(Object item, boolean isData) { 440 | UNSAFE.putObject(this, itemOffset, item); // relaxed write 441 | this.isData = isData; 442 | } 443 | 444 | /** 445 | * Links node to itself to avoid garbage retention. Called 446 | * only after CASing head field, so uses relaxed write. 447 | */ 448 | final void forgetNext() { 449 | UNSAFE.putObject(this, nextOffset, this); 450 | } 451 | 452 | /** 453 | * Sets item to self and waiter to null, to avoid garbage 454 | * retention after matching or cancelling. Uses relaxed writes 455 | * because order is already constrained in the only calling 456 | * contexts: item is forgotten only after volatile/atomic 457 | * mechanics that extract items. Similarly, clearing waiter 458 | * follows either CAS or return from park (if ever parked; 459 | * else we don't care). 460 | */ 461 | final void forgetContents() { 462 | UNSAFE.putObject(this, itemOffset, this); 463 | UNSAFE.putObject(this, waiterOffset, null); 464 | } 465 | 466 | /** 467 | * Returns true if this node has been matched, including the 468 | * case of artificial matches due to cancellation. 469 | */ 470 | final boolean isMatched() { 471 | Object x = item; 472 | return (x == this) || ((x == null) == isData); 473 | } 474 | 475 | /** 476 | * Returns true if this is an unmatched request node. 477 | */ 478 | final boolean isUnmatchedRequest() { 479 | return !isData && item == null; 480 | } 481 | 482 | /** 483 | * Returns true if a node with the given mode cannot be 484 | * appended to this node because this node is unmatched and 485 | * has opposite data mode. 486 | */ 487 | final boolean cannotPrecede(boolean haveData) { 488 | boolean d = isData; 489 | Object x; 490 | return d != haveData && (x = item) != this && (x != null) == d; 491 | } 492 | 493 | /** 494 | * Tries to artificially match a data node -- used by remove. 495 | */ 496 | final boolean tryMatchData() { 497 | // assert isData; 498 | Object x = item; 499 | if (x != null && x != this && casItem(x, null)) { 500 | LockSupport.unpark(waiter); 501 | return true; 502 | } 503 | return false; 504 | } 505 | 506 | private static final long serialVersionUID = -3375979862319811754L; 507 | 508 | // Unsafe mechanics 509 | private static final sun.misc.Unsafe UNSAFE; 510 | private static final long itemOffset; 511 | private static final long nextOffset; 512 | private static final long waiterOffset; 513 | static { 514 | try { 515 | UNSAFE = getUnsafe(); 516 | Class k = Node.class; 517 | itemOffset = UNSAFE.objectFieldOffset 518 | (k.getDeclaredField("item")); 519 | nextOffset = UNSAFE.objectFieldOffset 520 | (k.getDeclaredField("next")); 521 | waiterOffset = UNSAFE.objectFieldOffset 522 | (k.getDeclaredField("waiter")); 523 | } catch (Exception e) { 524 | throw new Error(e); 525 | } 526 | } 527 | } 528 | 529 | /** head of the queue; null until first enqueue */ 530 | transient volatile Node head; 531 | 532 | /** tail of the queue; null until first append */ 533 | private transient volatile Node tail; 534 | 535 | /** The number of apparent failures to unsplice removed nodes */ 536 | private transient volatile int sweepVotes; 537 | 538 | // CAS methods for fields 539 | private boolean casTail(Node cmp, Node val) { 540 | return UNSAFE.compareAndSwapObject(this, tailOffset, cmp, val); 541 | } 542 | 543 | private boolean casHead(Node cmp, Node val) { 544 | return UNSAFE.compareAndSwapObject(this, headOffset, cmp, val); 545 | } 546 | 547 | private boolean casSweepVotes(int cmp, int val) { 548 | return UNSAFE.compareAndSwapInt(this, sweepVotesOffset, cmp, val); 549 | } 550 | 551 | /* 552 | * Possible values for "how" argument in xfer method. 553 | */ 554 | private static final int NOW = 0; // for untimed poll, tryTransfer 555 | private static final int ASYNC = 1; // for offer, put, add 556 | private static final int SYNC = 2; // for transfer, take 557 | private static final int TIMED = 3; // for timed poll, tryTransfer 558 | 559 | @SuppressWarnings("unchecked") 560 | static E cast(Object item) { 561 | // assert item == null || item.getClass() != Node.class; 562 | return (E) item; 563 | } 564 | 565 | /** 566 | * Implements all queuing methods. See above for explanation. 567 | * 568 | * @param e the item or null for take 569 | * @param haveData true if this is a put, else a take 570 | * @param how NOW, ASYNC, SYNC, or TIMED 571 | * @param nanos timeout in nanosecs, used only if mode is TIMED 572 | * @return an item if matched, else e 573 | * @throws NullPointerException if haveData mode but e is null 574 | */ 575 | private E xfer(E e, boolean haveData, int how, long nanos) { 576 | if (haveData && (e == null)) 577 | throw new NullPointerException(); 578 | Node s = null; // the node to append, if needed 579 | 580 | retry: 581 | for (;;) { // restart on append race 582 | 583 | for (Node h = head, p = h; p != null;) { // find & match first node 584 | boolean isData = p.isData; 585 | Object item = p.item; 586 | if (item != p && (item != null) == isData) { // unmatched 587 | if (isData == haveData) // can't match 588 | break; 589 | if (p.casItem(item, e)) { // match 590 | for (Node q = p; q != h;) { 591 | Node n = q.next; // update by 2 unless singleton 592 | if (head == h && casHead(h, n == null ? q : n)) { 593 | h.forgetNext(); 594 | break; 595 | } // advance and retry 596 | if ((h = head) == null || 597 | (q = h.next) == null || !q.isMatched()) 598 | break; // unless slack < 2 599 | } 600 | LockSupport.unpark(p.waiter); 601 | return LinkedTransferQueue.cast(item); 602 | } 603 | } 604 | Node n = p.next; 605 | p = (p != n) ? n : (h = head); // Use head if p offlist 606 | } 607 | 608 | if (how != NOW) { // No matches available 609 | if (s == null) 610 | s = new Node(e, haveData); 611 | Node pred = tryAppend(s, haveData); 612 | if (pred == null) 613 | continue retry; // lost race vs opposite mode 614 | if (how != ASYNC) 615 | return awaitMatch(s, pred, e, (how == TIMED), nanos); 616 | } 617 | return e; // not waiting 618 | } 619 | } 620 | 621 | /** 622 | * Tries to append node s as tail. 623 | * 624 | * @param s the node to append 625 | * @param haveData true if appending in data mode 626 | * @return null on failure due to losing race with append in 627 | * different mode, else s's predecessor, or s itself if no 628 | * predecessor 629 | */ 630 | private Node tryAppend(Node s, boolean haveData) { 631 | for (Node t = tail, p = t;;) { // move p to last node and append 632 | Node n, u; // temps for reads of next & tail 633 | if (p == null && (p = head) == null) { 634 | if (casHead(null, s)) 635 | return s; // initialize 636 | } 637 | else if (p.cannotPrecede(haveData)) 638 | return null; // lost race vs opposite mode 639 | else if ((n = p.next) != null) // not last; keep traversing 640 | p = p != t && t != (u = tail) ? (t = u) : // stale tail 641 | (p != n) ? n : null; // restart if off list 642 | else if (!p.casNext(null, s)) 643 | p = p.next; // re-read on CAS failure 644 | else { 645 | if (p != t) { // update if slack now >= 2 646 | while ((tail != t || !casTail(t, s)) && 647 | (t = tail) != null && 648 | (s = t.next) != null && // advance and retry 649 | (s = s.next) != null && s != t); 650 | } 651 | return p; 652 | } 653 | } 654 | } 655 | 656 | /** 657 | * Spins/yields/blocks until node s is matched or caller gives up. 658 | * 659 | * @param s the waiting node 660 | * @param pred the predecessor of s, or s itself if it has no 661 | * predecessor, or null if unknown (the null case does not occur 662 | * in any current calls but may in possible future extensions) 663 | * @param e the comparison value for checking match 664 | * @param timed if true, wait only until timeout elapses 665 | * @param nanos timeout in nanosecs, used only if timed is true 666 | * @return matched item, or e if unmatched on interrupt or timeout 667 | */ 668 | private E awaitMatch(Node s, Node pred, E e, boolean timed, long nanos) { 669 | long lastTime = timed ? System.nanoTime() : 0L; 670 | Thread w = Thread.currentThread(); 671 | int spins = -1; // initialized after first item and cancel checks 672 | ThreadLocalRandom randomYields = null; // bound if needed 673 | 674 | for (;;) { 675 | Object item = s.item; 676 | if (item != e) { // matched 677 | // assert item != s; 678 | s.forgetContents(); // avoid garbage 679 | return LinkedTransferQueue.cast(item); 680 | } 681 | if ((w.isInterrupted() || (timed && nanos <= 0)) && 682 | s.casItem(e, s)) { // cancel 683 | unsplice(pred, s); 684 | return e; 685 | } 686 | 687 | if (spins < 0) { // establish spins at/near front 688 | if ((spins = spinsFor(pred, s.isData)) > 0) 689 | randomYields = ThreadLocalRandom.current(); 690 | } 691 | else if (spins > 0) { // spin 692 | --spins; 693 | if (randomYields.nextInt(CHAINED_SPINS) == 0) 694 | Thread.yield(); // occasionally yield 695 | } 696 | else if (s.waiter == null) { 697 | s.waiter = w; // request unpark then recheck 698 | } 699 | else if (timed) { 700 | long now = System.nanoTime(); 701 | if ((nanos -= now - lastTime) > 0) 702 | LockSupport.parkNanos(this, nanos); 703 | lastTime = now; 704 | } 705 | else { 706 | LockSupport.park(this); 707 | } 708 | } 709 | } 710 | 711 | /** 712 | * Returns spin/yield value for a node with given predecessor and 713 | * data mode. See above for explanation. 714 | */ 715 | private static int spinsFor(Node pred, boolean haveData) { 716 | if (MP && pred != null) { 717 | if (pred.isData != haveData) // phase change 718 | return FRONT_SPINS + CHAINED_SPINS; 719 | if (pred.isMatched()) // probably at front 720 | return FRONT_SPINS; 721 | if (pred.waiter == null) // pred apparently spinning 722 | return CHAINED_SPINS; 723 | } 724 | return 0; 725 | } 726 | 727 | /* -------------- Traversal methods -------------- */ 728 | 729 | /** 730 | * Returns the successor of p, or the head node if p.next has been 731 | * linked to self, which will only be true if traversing with a 732 | * stale pointer that is now off the list. 733 | */ 734 | final Node succ(Node p) { 735 | Node next = p.next; 736 | return (p == next) ? head : next; 737 | } 738 | 739 | /** 740 | * Returns the first unmatched node of the given mode, or null if 741 | * none. Used by methods isEmpty, hasWaitingConsumer. 742 | */ 743 | private Node firstOfMode(boolean isData) { 744 | for (Node p = head; p != null; p = succ(p)) { 745 | if (!p.isMatched()) 746 | return (p.isData == isData) ? p : null; 747 | } 748 | return null; 749 | } 750 | 751 | /** 752 | * Returns the item in the first unmatched node with isData; or 753 | * null if none. Used by peek. 754 | */ 755 | private E firstDataItem() { 756 | for (Node p = head; p != null; p = succ(p)) { 757 | Object item = p.item; 758 | if (p.isData) { 759 | if (item != null && item != p) 760 | return LinkedTransferQueue.cast(item); 761 | } 762 | else if (item == null) 763 | return null; 764 | } 765 | return null; 766 | } 767 | 768 | /** 769 | * Traverses and counts unmatched nodes of the given mode. 770 | * Used by methods size and getWaitingConsumerCount. 771 | */ 772 | private int countOfMode(boolean data) { 773 | int count = 0; 774 | for (Node p = head; p != null; ) { 775 | if (!p.isMatched()) { 776 | if (p.isData != data) 777 | return 0; 778 | if (++count == Integer.MAX_VALUE) // saturated 779 | break; 780 | } 781 | Node n = p.next; 782 | if (n != p) 783 | p = n; 784 | else { 785 | count = 0; 786 | p = head; 787 | } 788 | } 789 | return count; 790 | } 791 | 792 | final class Itr implements Iterator { 793 | private Node nextNode; // next node to return item for 794 | private E nextItem; // the corresponding item 795 | private Node lastRet; // last returned node, to support remove 796 | private Node lastPred; // predecessor to unlink lastRet 797 | 798 | /** 799 | * Moves to next node after prev, or first node if prev null. 800 | */ 801 | private void advance(Node prev) { 802 | /* 803 | * To track and avoid buildup of deleted nodes in the face 804 | * of calls to both Queue.remove and Itr.remove, we must 805 | * include variants of unsplice and sweep upon each 806 | * advance: Upon Itr.remove, we may need to catch up links 807 | * from lastPred, and upon other removes, we might need to 808 | * skip ahead from stale nodes and unsplice deleted ones 809 | * found while advancing. 810 | */ 811 | 812 | Node r, b; // reset lastPred upon possible deletion of lastRet 813 | if ((r = lastRet) != null && !r.isMatched()) 814 | lastPred = r; // next lastPred is old lastRet 815 | else if ((b = lastPred) == null || b.isMatched()) 816 | lastPred = null; // at start of list 817 | else { 818 | Node s, n; // help with removal of lastPred.next 819 | while ((s = b.next) != null && 820 | s != b && s.isMatched() && 821 | (n = s.next) != null && n != s) 822 | b.casNext(s, n); 823 | } 824 | 825 | this.lastRet = prev; 826 | 827 | for (Node p = prev, s, n;;) { 828 | s = (p == null) ? head : p.next; 829 | if (s == null) 830 | break; 831 | else if (s == p) { 832 | p = null; 833 | continue; 834 | } 835 | Object item = s.item; 836 | if (s.isData) { 837 | if (item != null && item != s) { 838 | nextItem = LinkedTransferQueue.cast(item); 839 | nextNode = s; 840 | return; 841 | } 842 | } 843 | else if (item == null) 844 | break; 845 | // assert s.isMatched(); 846 | if (p == null) 847 | p = s; 848 | else if ((n = s.next) == null) 849 | break; 850 | else if (s == n) 851 | p = null; 852 | else 853 | p.casNext(s, n); 854 | } 855 | nextNode = null; 856 | nextItem = null; 857 | } 858 | 859 | Itr() { 860 | advance(null); 861 | } 862 | 863 | public final boolean hasNext() { 864 | return nextNode != null; 865 | } 866 | 867 | public final E next() { 868 | Node p = nextNode; 869 | if (p == null) throw new NoSuchElementException(); 870 | E e = nextItem; 871 | advance(p); 872 | return e; 873 | } 874 | 875 | public final void remove() { 876 | final Node lastRet = this.lastRet; 877 | if (lastRet == null) 878 | throw new IllegalStateException(); 879 | this.lastRet = null; 880 | if (lastRet.tryMatchData()) 881 | unsplice(lastPred, lastRet); 882 | } 883 | } 884 | 885 | /* -------------- Removal methods -------------- */ 886 | 887 | /** 888 | * Unsplices (now or later) the given deleted/cancelled node with 889 | * the given predecessor. 890 | * 891 | * @param pred a node that was at one time known to be the 892 | * predecessor of s, or null or s itself if s is/was at head 893 | * @param s the node to be unspliced 894 | */ 895 | final void unsplice(Node pred, Node s) { 896 | s.forgetContents(); // forget unneeded fields 897 | /* 898 | * See above for rationale. Briefly: if pred still points to 899 | * s, try to unlink s. If s cannot be unlinked, because it is 900 | * trailing node or pred might be unlinked, and neither pred 901 | * nor s are head or offlist, add to sweepVotes, and if enough 902 | * votes have accumulated, sweep. 903 | */ 904 | if (pred != null && pred != s && pred.next == s) { 905 | Node n = s.next; 906 | if (n == null || 907 | (n != s && pred.casNext(s, n) && pred.isMatched())) { 908 | for (;;) { // check if at, or could be, head 909 | Node h = head; 910 | if (h == pred || h == s || h == null) 911 | return; // at head or list empty 912 | if (!h.isMatched()) 913 | break; 914 | Node hn = h.next; 915 | if (hn == null) 916 | return; // now empty 917 | if (hn != h && casHead(h, hn)) 918 | h.forgetNext(); // advance head 919 | } 920 | if (pred.next != pred && s.next != s) { // recheck if offlist 921 | for (;;) { // sweep now if enough votes 922 | int v = sweepVotes; 923 | if (v < SWEEP_THRESHOLD) { 924 | if (casSweepVotes(v, v + 1)) 925 | break; 926 | } 927 | else if (casSweepVotes(v, 0)) { 928 | sweep(); 929 | break; 930 | } 931 | } 932 | } 933 | } 934 | } 935 | } 936 | 937 | /** 938 | * Unlinks matched (typically cancelled) nodes encountered in a 939 | * traversal from head. 940 | */ 941 | private void sweep() { 942 | for (Node p = head, s, n; p != null && (s = p.next) != null; ) { 943 | if (!s.isMatched()) 944 | // Unmatched nodes are never self-linked 945 | p = s; 946 | else if ((n = s.next) == null) // trailing node is pinned 947 | break; 948 | else if (s == n) // stale 949 | // No need to also check for p == s, since that implies s == n 950 | p = head; 951 | else 952 | p.casNext(s, n); 953 | } 954 | } 955 | 956 | /** 957 | * Main implementation of remove(Object) 958 | */ 959 | private boolean findAndRemove(Object e) { 960 | if (e != null) { 961 | for (Node pred = null, p = head; p != null; ) { 962 | Object item = p.item; 963 | if (p.isData) { 964 | if (item != null && item != p && e.equals(item) && 965 | p.tryMatchData()) { 966 | unsplice(pred, p); 967 | return true; 968 | } 969 | } 970 | else if (item == null) 971 | break; 972 | pred = p; 973 | if ((p = p.next) == pred) { // stale 974 | pred = null; 975 | p = head; 976 | } 977 | } 978 | } 979 | return false; 980 | } 981 | 982 | 983 | /** 984 | * Creates an initially empty {@code LinkedTransferQueue}. 985 | */ 986 | public LinkedTransferQueue() { 987 | } 988 | 989 | /** 990 | * Creates a {@code LinkedTransferQueue} 991 | * initially containing the elements of the given collection, 992 | * added in traversal order of the collection's iterator. 993 | * 994 | * @param c the collection of elements to initially contain 995 | * @throws NullPointerException if the specified collection or any 996 | * of its elements are null 997 | */ 998 | public LinkedTransferQueue(Collection c) { 999 | this(); 1000 | addAll(c); 1001 | } 1002 | 1003 | /** 1004 | * Inserts the specified element at the tail of this queue. 1005 | * As the queue is unbounded, this method will never block. 1006 | * 1007 | * @throws NullPointerException if the specified element is null 1008 | */ 1009 | public void put(E e) { 1010 | xfer(e, true, ASYNC, 0); 1011 | } 1012 | 1013 | /** 1014 | * Inserts the specified element at the tail of this queue. 1015 | * As the queue is unbounded, this method will never block or 1016 | * return {@code false}. 1017 | * 1018 | * @return {@code true} (as specified by 1019 | * {@link java.util.concurrent.BlockingQueue#offer(Object,long,TimeUnit) 1020 | * BlockingQueue.offer}) 1021 | * @throws NullPointerException if the specified element is null 1022 | */ 1023 | public boolean offer(E e, long timeout, TimeUnit unit) { 1024 | xfer(e, true, ASYNC, 0); 1025 | return true; 1026 | } 1027 | 1028 | /** 1029 | * Inserts the specified element at the tail of this queue. 1030 | * As the queue is unbounded, this method will never return {@code false}. 1031 | * 1032 | * @return {@code true} (as specified by {@link Queue#offer}) 1033 | * @throws NullPointerException if the specified element is null 1034 | */ 1035 | public boolean offer(E e) { 1036 | xfer(e, true, ASYNC, 0); 1037 | return true; 1038 | } 1039 | 1040 | /** 1041 | * Inserts the specified element at the tail of this queue. 1042 | * As the queue is unbounded, this method will never throw 1043 | * {@link IllegalStateException} or return {@code false}. 1044 | * 1045 | * @return {@code true} (as specified by {@link Collection#add}) 1046 | * @throws NullPointerException if the specified element is null 1047 | */ 1048 | public boolean add(E e) { 1049 | xfer(e, true, ASYNC, 0); 1050 | return true; 1051 | } 1052 | 1053 | /** 1054 | * Transfers the element to a waiting consumer immediately, if possible. 1055 | * 1056 | *

More precisely, transfers the specified element immediately 1057 | * if there exists a consumer already waiting to receive it (in 1058 | * {@link #take} or timed {@link #poll(long,TimeUnit) poll}), 1059 | * otherwise returning {@code false} without enqueuing the element. 1060 | * 1061 | * @throws NullPointerException if the specified element is null 1062 | */ 1063 | public boolean tryTransfer(E e) { 1064 | return xfer(e, true, NOW, 0) == null; 1065 | } 1066 | 1067 | /** 1068 | * Transfers the element to a consumer, waiting if necessary to do so. 1069 | * 1070 | *

More precisely, transfers the specified element immediately 1071 | * if there exists a consumer already waiting to receive it (in 1072 | * {@link #take} or timed {@link #poll(long,TimeUnit) poll}), 1073 | * else inserts the specified element at the tail of this queue 1074 | * and waits until the element is received by a consumer. 1075 | * 1076 | * @throws NullPointerException if the specified element is null 1077 | */ 1078 | public void transfer(E e) throws InterruptedException { 1079 | if (xfer(e, true, SYNC, 0) != null) { 1080 | Thread.interrupted(); // failure possible only due to interrupt 1081 | throw new InterruptedException(); 1082 | } 1083 | } 1084 | 1085 | /** 1086 | * Transfers the element to a consumer if it is possible to do so 1087 | * before the timeout elapses. 1088 | * 1089 | *

More precisely, transfers the specified element immediately 1090 | * if there exists a consumer already waiting to receive it (in 1091 | * {@link #take} or timed {@link #poll(long,TimeUnit) poll}), 1092 | * else inserts the specified element at the tail of this queue 1093 | * and waits until the element is received by a consumer, 1094 | * returning {@code false} if the specified wait time elapses 1095 | * before the element can be transferred. 1096 | * 1097 | * @throws NullPointerException if the specified element is null 1098 | */ 1099 | public boolean tryTransfer(E e, long timeout, TimeUnit unit) 1100 | throws InterruptedException { 1101 | if (xfer(e, true, TIMED, unit.toNanos(timeout)) == null) 1102 | return true; 1103 | if (!Thread.interrupted()) 1104 | return false; 1105 | throw new InterruptedException(); 1106 | } 1107 | 1108 | public E take() throws InterruptedException { 1109 | E e = xfer(null, false, SYNC, 0); 1110 | if (e != null) 1111 | return e; 1112 | Thread.interrupted(); 1113 | throw new InterruptedException(); 1114 | } 1115 | 1116 | public E poll(long timeout, TimeUnit unit) throws InterruptedException { 1117 | E e = xfer(null, false, TIMED, unit.toNanos(timeout)); 1118 | if (e != null || !Thread.interrupted()) 1119 | return e; 1120 | throw new InterruptedException(); 1121 | } 1122 | 1123 | public E poll() { 1124 | return xfer(null, false, NOW, 0); 1125 | } 1126 | 1127 | /** 1128 | * @throws NullPointerException {@inheritDoc} 1129 | * @throws IllegalArgumentException {@inheritDoc} 1130 | */ 1131 | public int drainTo(Collection c) { 1132 | if (c == null) 1133 | throw new NullPointerException(); 1134 | if (c == this) 1135 | throw new IllegalArgumentException(); 1136 | int n = 0; 1137 | for (E e; (e = poll()) != null;) { 1138 | c.add(e); 1139 | ++n; 1140 | } 1141 | return n; 1142 | } 1143 | 1144 | /** 1145 | * @throws NullPointerException {@inheritDoc} 1146 | * @throws IllegalArgumentException {@inheritDoc} 1147 | */ 1148 | public int drainTo(Collection c, int maxElements) { 1149 | if (c == null) 1150 | throw new NullPointerException(); 1151 | if (c == this) 1152 | throw new IllegalArgumentException(); 1153 | int n = 0; 1154 | for (E e; n < maxElements && (e = poll()) != null;) { 1155 | c.add(e); 1156 | ++n; 1157 | } 1158 | return n; 1159 | } 1160 | 1161 | /** 1162 | * Returns an iterator over the elements in this queue in proper sequence. 1163 | * The elements will be returned in order from first (head) to last (tail). 1164 | * 1165 | *

The returned iterator is a "weakly consistent" iterator that 1166 | * will never throw {@link java.util.ConcurrentModificationException 1167 | * ConcurrentModificationException}, and guarantees to traverse 1168 | * elements as they existed upon construction of the iterator, and 1169 | * may (but is not guaranteed to) reflect any modifications 1170 | * subsequent to construction. 1171 | * 1172 | * @return an iterator over the elements in this queue in proper sequence 1173 | */ 1174 | public Iterator iterator() { 1175 | return new Itr(); 1176 | } 1177 | 1178 | public E peek() { 1179 | return firstDataItem(); 1180 | } 1181 | 1182 | /** 1183 | * Returns {@code true} if this queue contains no elements. 1184 | * 1185 | * @return {@code true} if this queue contains no elements 1186 | */ 1187 | public boolean isEmpty() { 1188 | for (Node p = head; p != null; p = succ(p)) { 1189 | if (!p.isMatched()) 1190 | return !p.isData; 1191 | } 1192 | return true; 1193 | } 1194 | 1195 | public boolean hasWaitingConsumer() { 1196 | return firstOfMode(false) != null; 1197 | } 1198 | 1199 | /** 1200 | * Returns the number of elements in this queue. If this queue 1201 | * contains more than {@code Integer.MAX_VALUE} elements, returns 1202 | * {@code Integer.MAX_VALUE}. 1203 | * 1204 | *

Beware that, unlike in most collections, this method is 1205 | * NOT a constant-time operation. Because of the 1206 | * asynchronous nature of these queues, determining the current 1207 | * number of elements requires an O(n) traversal. 1208 | * 1209 | * @return the number of elements in this queue 1210 | */ 1211 | public int size() { 1212 | return countOfMode(true); 1213 | } 1214 | 1215 | public int getWaitingConsumerCount() { 1216 | return countOfMode(false); 1217 | } 1218 | 1219 | /** 1220 | * Removes a single instance of the specified element from this queue, 1221 | * if it is present. More formally, removes an element {@code e} such 1222 | * that {@code o.equals(e)}, if this queue contains one or more such 1223 | * elements. 1224 | * Returns {@code true} if this queue contained the specified element 1225 | * (or equivalently, if this queue changed as a result of the call). 1226 | * 1227 | * @param o element to be removed from this queue, if present 1228 | * @return {@code true} if this queue changed as a result of the call 1229 | */ 1230 | public boolean remove(Object o) { 1231 | return findAndRemove(o); 1232 | } 1233 | 1234 | /** 1235 | * Returns {@code true} if this queue contains the specified element. 1236 | * More formally, returns {@code true} if and only if this queue contains 1237 | * at least one element {@code e} such that {@code o.equals(e)}. 1238 | * 1239 | * @param o object to be checked for containment in this queue 1240 | * @return {@code true} if this queue contains the specified element 1241 | */ 1242 | public boolean contains(Object o) { 1243 | if (o == null) return false; 1244 | for (Node p = head; p != null; p = succ(p)) { 1245 | Object item = p.item; 1246 | if (p.isData) { 1247 | if (item != null && item != p && o.equals(item)) 1248 | return true; 1249 | } 1250 | else if (item == null) 1251 | break; 1252 | } 1253 | return false; 1254 | } 1255 | 1256 | /** 1257 | * Always returns {@code Integer.MAX_VALUE} because a 1258 | * {@code LinkedTransferQueue} is not capacity constrained. 1259 | * 1260 | * @return {@code Integer.MAX_VALUE} (as specified by 1261 | * {@link java.util.concurrent.BlockingQueue#remainingCapacity() 1262 | * BlockingQueue.remainingCapacity}) 1263 | */ 1264 | public int remainingCapacity() { 1265 | return Integer.MAX_VALUE; 1266 | } 1267 | 1268 | /** 1269 | * Saves the state to a stream (that is, serializes it). 1270 | * 1271 | * @serialData All of the elements (each an {@code E}) in 1272 | * the proper order, followed by a null 1273 | * @param s the stream 1274 | */ 1275 | private void writeObject(java.io.ObjectOutputStream s) 1276 | throws java.io.IOException { 1277 | s.defaultWriteObject(); 1278 | for (E e : this) 1279 | s.writeObject(e); 1280 | // Use trailing null as sentinel 1281 | s.writeObject(null); 1282 | } 1283 | 1284 | /** 1285 | * Reconstitutes the Queue instance from a stream (that is, 1286 | * deserializes it). 1287 | * 1288 | * @param s the stream 1289 | */ 1290 | private void readObject(java.io.ObjectInputStream s) 1291 | throws java.io.IOException, ClassNotFoundException { 1292 | s.defaultReadObject(); 1293 | for (;;) { 1294 | @SuppressWarnings("unchecked") 1295 | E item = (E) s.readObject(); 1296 | if (item == null) 1297 | break; 1298 | else 1299 | offer(item); 1300 | } 1301 | } 1302 | 1303 | // Unsafe mechanics 1304 | 1305 | private static final sun.misc.Unsafe UNSAFE; 1306 | private static final long headOffset; 1307 | private static final long tailOffset; 1308 | private static final long sweepVotesOffset; 1309 | static { 1310 | try { 1311 | UNSAFE = getUnsafe(); 1312 | Class k = LinkedTransferQueue.class; 1313 | headOffset = UNSAFE.objectFieldOffset 1314 | (k.getDeclaredField("head")); 1315 | tailOffset = UNSAFE.objectFieldOffset 1316 | (k.getDeclaredField("tail")); 1317 | sweepVotesOffset = UNSAFE.objectFieldOffset 1318 | (k.getDeclaredField("sweepVotes")); 1319 | } catch (Exception e) { 1320 | throw new Error(e); 1321 | } 1322 | } 1323 | 1324 | /** 1325 | * Returns a sun.misc.Unsafe. Suitable for use in a 3rd party package. 1326 | * Replace with a simple call to Unsafe.getUnsafe when integrating 1327 | * into a jdk. 1328 | * 1329 | * @return a sun.misc.Unsafe 1330 | */ 1331 | static sun.misc.Unsafe getUnsafe() { 1332 | return monix.forkJoin.Unsafe.instance; 1333 | } 1334 | 1335 | } 1336 | -------------------------------------------------------------------------------- /src/main/java/monix/forkJoin/ForkJoinTask.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Written by Doug Lea with assistance from members of JCP JSR-166 3 | * Expert Group and released to the public domain, as explained at 4 | * http://creativecommons.org/publicdomain/zero/1.0/ 5 | */ 6 | 7 | package monix.forkJoin; 8 | 9 | import java.io.Serializable; 10 | import java.util.Collection; 11 | import java.util.List; 12 | import java.util.RandomAccess; 13 | import java.lang.ref.WeakReference; 14 | import java.lang.ref.ReferenceQueue; 15 | import java.util.concurrent.Callable; 16 | import java.util.concurrent.CancellationException; 17 | import java.util.concurrent.ExecutionException; 18 | import java.util.concurrent.Future; 19 | import java.util.concurrent.RejectedExecutionException; 20 | import java.util.concurrent.RunnableFuture; 21 | import java.util.concurrent.TimeUnit; 22 | import java.util.concurrent.TimeoutException; 23 | import java.util.concurrent.locks.ReentrantLock; 24 | import java.lang.reflect.Constructor; 25 | 26 | /** 27 | * Abstract base class for tasks that run within a {@link ForkJoinPool}. 28 | * A {@code ForkJoinTask} is a thread-like entity that is much 29 | * lighter weight than a normal thread. Huge numbers of tasks and 30 | * subtasks may be hosted by a small number of actual threads in a 31 | * ForkJoinPool, at the price of some usage limitations. 32 | * 33 | *

A "main" {@code ForkJoinTask} begins execution when it is 34 | * explicitly submitted to a {@link ForkJoinPool}, or, if not already 35 | * engaged in a ForkJoin computation, commenced in the {@link 36 | * ForkJoinPool#commonPool()} via {@link #fork}, {@link #invoke}, or 37 | * related methods. Once started, it will usually in turn start other 38 | * subtasks. As indicated by the name of this class, many programs 39 | * using {@code ForkJoinTask} employ only methods {@link #fork} and 40 | * {@link #join}, or derivatives such as {@link 41 | * #invokeAll(ForkJoinTask...) invokeAll}. However, this class also 42 | * provides a number of other methods that can come into play in 43 | * advanced usages, as well as extension mechanics that allow support 44 | * of new forms of fork/join processing. 45 | * 46 | *

A {@code ForkJoinTask} is a lightweight form of {@link Future}. 47 | * The efficiency of {@code ForkJoinTask}s stems from a set of 48 | * restrictions (that are only partially statically enforceable) 49 | * reflecting their main use as computational tasks calculating pure 50 | * functions or operating on purely isolated objects. The primary 51 | * coordination mechanisms are {@link #fork}, that arranges 52 | * asynchronous execution, and {@link #join}, that doesn't proceed 53 | * until the task's result has been computed. Computations should 54 | * ideally avoid {@code synchronized} methods or blocks, and should 55 | * minimize other blocking synchronization apart from joining other 56 | * tasks or using synchronizers such as Phasers that are advertised to 57 | * cooperate with fork/join scheduling. Subdividable tasks should also 58 | * not perform blocking I/O, and should ideally access variables that 59 | * are completely independent of those accessed by other running 60 | * tasks. These guidelines are loosely enforced by not permitting 61 | * checked exceptions such as {@code IOExceptions} to be 62 | * thrown. However, computations may still encounter unchecked 63 | * exceptions, that are rethrown to callers attempting to join 64 | * them. These exceptions may additionally include {@link 65 | * RejectedExecutionException} stemming from internal resource 66 | * exhaustion, such as failure to allocate internal task 67 | * queues. Rethrown exceptions behave in the same way as regular 68 | * exceptions, but, when possible, contain stack traces (as displayed 69 | * for example using {@code ex.printStackTrace()}) of both the thread 70 | * that initiated the computation as well as the thread actually 71 | * encountering the exception; minimally only the latter. 72 | * 73 | *

It is possible to define and use ForkJoinTasks that may block, 74 | * but doing do requires three further considerations: (1) Completion 75 | * of few if any other tasks should be dependent on a task 76 | * that blocks on external synchronization or I/O. Event-style async 77 | * tasks that are never joined (for example, those subclassing {@link 78 | * CountedCompleter}) often fall into this category. (2) To minimize 79 | * resource impact, tasks should be small; ideally performing only the 80 | * (possibly) blocking action. (3) Unless the {@link 81 | * ForkJoinPool.ManagedBlocker} API is used, or the number of possibly 82 | * blocked tasks is known to be less than the pool's {@link 83 | * ForkJoinPool#getParallelism} level, the pool cannot guarantee that 84 | * enough threads will be available to ensure progress or good 85 | * performance. 86 | * 87 | *

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

In the most typical usages, a fork-join pair act like a call 102 | * (fork) and return (join) from a parallel recursive function. As is 103 | * the case with other forms of recursive calls, returns (joins) 104 | * should be performed innermost-first. For example, {@code a.fork(); 105 | * b.fork(); b.join(); a.join();} is likely to be substantially more 106 | * efficient than joining {@code a} before {@code b}. 107 | * 108 | *

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

The ForkJoinTask class is not usually directly subclassed. 121 | * Instead, you subclass one of the abstract classes that support a 122 | * particular style of fork/join processing, typically {@link 123 | * RecursiveAction} for most computations that do not return results, 124 | * {@link RecursiveTask} for those that do, and {@link 125 | * CountedCompleter} for those in which completed actions trigger 126 | * other actions. Normally, a concrete ForkJoinTask subclass declares 127 | * fields comprising its parameters, established in a constructor, and 128 | * then defines a {@code compute} method that somehow uses the control 129 | * methods supplied by this base class. 130 | * 131 | *

Method {@link #join} and its variants are appropriate for use 132 | * only when completion dependencies are acyclic; that is, the 133 | * parallel computation can be described as a directed acyclic graph 134 | * (DAG). Otherwise, executions may encounter a form of deadlock as 135 | * tasks cyclically wait for each other. However, this framework 136 | * supports other methods and techniques (for example the use of 137 | * {@link Phaser}, {@link #helpQuiesce}, and {@link #complete}) that 138 | * may be of use in constructing custom subclasses for problems that 139 | * are not statically structured as DAGs. To support such usages a 140 | * ForkJoinTask may be atomically tagged with a {@code short} 141 | * value using {@link #setForkJoinTaskTag} or {@link 142 | * #compareAndSetForkJoinTaskTag} and checked using {@link 143 | * #getForkJoinTaskTag}. The ForkJoinTask implementation does not use 144 | * these {@code protected} methods or tags for any purpose, but they 145 | * may be of use in the construction of specialized subclasses. For 146 | * example, parallel graph traversals can use the supplied methods to 147 | * avoid revisiting nodes/tasks that have already been processed. 148 | * (Method names for tagging are bulky in part to encourage definition 149 | * of methods that reflect their usage patterns.) 150 | * 151 | *

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

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

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

ForkJoinTasks are {@code Serializable}, which enables them to be 176 | * used in extensions such as remote execution frameworks. It is 177 | * sensible to serialize tasks only before or after, but not during, 178 | * execution. Serialization is not relied on during execution itself. 179 | * 180 | * @since 1.7 181 | * @author Doug Lea 182 | */ 183 | public abstract class ForkJoinTask implements Future, Serializable { 184 | 185 | /* 186 | * See the internal documentation of class ForkJoinPool for a 187 | * general implementation overview. ForkJoinTasks are mainly 188 | * responsible for maintaining their "status" field amidst relays 189 | * to methods in ForkJoinWorkerThread and ForkJoinPool. 190 | * 191 | * The methods of this class are more-or-less layered into 192 | * (1) basic status maintenance 193 | * (2) execution and awaiting completion 194 | * (3) user-level methods that additionally report results. 195 | * This is sometimes hard to see because this file orders exported 196 | * methods in a way that flows well in javadocs. 197 | */ 198 | 199 | /* 200 | * The status field holds run control status bits packed into a 201 | * single int to minimize footprint and to ensure atomicity (via 202 | * CAS). Status is initially zero, and takes on nonnegative 203 | * values until completed, upon which status (anded with 204 | * DONE_MASK) holds value NORMAL, CANCELLED, or EXCEPTIONAL. Tasks 205 | * undergoing blocking waits by other threads have the SIGNAL bit 206 | * set. Completion of a stolen task with SIGNAL set awakens any 207 | * waiters via notifyAll. Even though suboptimal for some 208 | * purposes, we use basic builtin wait/notify to take advantage of 209 | * "monitor inflation" in JVMs that we would otherwise need to 210 | * emulate to avoid adding further per-task bookkeeping overhead. 211 | * We want these monitors to be "fat", i.e., not use biasing or 212 | * thin-lock techniques, so use some odd coding idioms that tend 213 | * to avoid them, mainly by arranging that every synchronized 214 | * block performs a wait, notifyAll or both. 215 | * 216 | * These control bits occupy only (some of) the upper half (16 217 | * bits) of status field. The lower bits are used for user-defined 218 | * tags. 219 | */ 220 | 221 | /** The run status of this task */ 222 | volatile int status; // accessed directly by pool and workers 223 | static final int DONE_MASK = 0xf0000000; // mask out non-completion bits 224 | static final int NORMAL = 0xf0000000; // must be negative 225 | static final int CANCELLED = 0xc0000000; // must be < NORMAL 226 | static final int EXCEPTIONAL = 0x80000000; // must be < CANCELLED 227 | static final int SIGNAL = 0x00010000; // must be >= 1 << 16 228 | static final int SMASK = 0x0000ffff; // short bits for tags 229 | 230 | /** 231 | * Marks completion and wakes up threads waiting to join this 232 | * task. 233 | * 234 | * @param completion one of NORMAL, CANCELLED, EXCEPTIONAL 235 | * @return completion status on exit 236 | */ 237 | private int setCompletion(int completion) { 238 | for (int s;;) { 239 | if ((s = status) < 0) 240 | return s; 241 | if (U.compareAndSwapInt(this, STATUS, s, s | completion)) { 242 | if ((s >>> 16) != 0) 243 | synchronized (this) { notifyAll(); } 244 | return completion; 245 | } 246 | } 247 | } 248 | 249 | /** 250 | * Primary execution method for stolen tasks. Unless done, calls 251 | * exec and records status if completed, but doesn't wait for 252 | * completion otherwise. 253 | * 254 | * @return status on exit from this method 255 | */ 256 | final int doExec() { 257 | int s; boolean completed; 258 | if ((s = status) >= 0) { 259 | try { 260 | completed = exec(); 261 | } catch (Throwable rex) { 262 | return setExceptionalCompletion(rex); 263 | } 264 | if (completed) 265 | s = setCompletion(NORMAL); 266 | } 267 | return s; 268 | } 269 | 270 | /** 271 | * Tries to set SIGNAL status unless already completed. Used by 272 | * ForkJoinPool. Other variants are directly incorporated into 273 | * externalAwaitDone etc. 274 | * 275 | * @return true if successful 276 | */ 277 | final boolean trySetSignal() { 278 | int s = status; 279 | return s >= 0 && U.compareAndSwapInt(this, STATUS, s, s | SIGNAL); 280 | } 281 | 282 | /** 283 | * Blocks a non-worker-thread until completion. 284 | * @return status upon completion 285 | */ 286 | private int externalAwaitDone() { 287 | int s; 288 | ForkJoinPool.externalHelpJoin(this); 289 | boolean interrupted = false; 290 | while ((s = status) >= 0) { 291 | if (U.compareAndSwapInt(this, STATUS, s, s | SIGNAL)) { 292 | synchronized (this) { 293 | if (status >= 0) { 294 | try { 295 | wait(); 296 | } catch (InterruptedException ie) { 297 | interrupted = true; 298 | } 299 | } 300 | else 301 | notifyAll(); 302 | } 303 | } 304 | } 305 | if (interrupted) 306 | Thread.currentThread().interrupt(); 307 | return s; 308 | } 309 | 310 | /** 311 | * Blocks a non-worker-thread until completion or interruption. 312 | */ 313 | private int externalInterruptibleAwaitDone() throws InterruptedException { 314 | int s; 315 | if (Thread.interrupted()) 316 | throw new InterruptedException(); 317 | ForkJoinPool.externalHelpJoin(this); 318 | while ((s = status) >= 0) { 319 | if (U.compareAndSwapInt(this, STATUS, s, s | SIGNAL)) { 320 | synchronized (this) { 321 | if (status >= 0) 322 | wait(); 323 | else 324 | notifyAll(); 325 | } 326 | } 327 | } 328 | return s; 329 | } 330 | 331 | 332 | /** 333 | * Implementation for join, get, quietlyJoin. Directly handles 334 | * only cases of already-completed, external wait, and 335 | * unfork+exec. Others are relayed to ForkJoinPool.awaitJoin. 336 | * 337 | * @return status upon completion 338 | */ 339 | private int doJoin() { 340 | int s; Thread t; ForkJoinWorkerThread wt; ForkJoinPool.WorkQueue w; 341 | return (s = status) < 0 ? s : 342 | ((t = Thread.currentThread()) instanceof ForkJoinWorkerThread) ? 343 | (w = (wt = (ForkJoinWorkerThread)t).workQueue). 344 | tryUnpush(this) && (s = doExec()) < 0 ? s : 345 | wt.pool.awaitJoin(w, this) : 346 | externalAwaitDone(); 347 | } 348 | 349 | /** 350 | * Implementation for invoke, quietlyInvoke. 351 | * 352 | * @return status upon completion 353 | */ 354 | private int doInvoke() { 355 | int s; Thread t; ForkJoinWorkerThread wt; 356 | return (s = doExec()) < 0 ? s : 357 | ((t = Thread.currentThread()) instanceof ForkJoinWorkerThread) ? 358 | (wt = (ForkJoinWorkerThread)t).pool.awaitJoin(wt.workQueue, this) : 359 | externalAwaitDone(); 360 | } 361 | 362 | // Exception table support 363 | 364 | /** 365 | * Table of exceptions thrown by tasks, to enable reporting by 366 | * callers. Because exceptions are rare, we don't directly keep 367 | * them with task objects, but instead use a weak ref table. Note 368 | * that cancellation exceptions don't appear in the table, but are 369 | * instead recorded as status values. 370 | * 371 | * Note: These statics are initialized below in static block. 372 | */ 373 | private static final ExceptionNode[] exceptionTable; 374 | private static final ReentrantLock exceptionTableLock; 375 | private static final ReferenceQueue exceptionTableRefQueue; 376 | 377 | /** 378 | * Fixed capacity for exceptionTable. 379 | */ 380 | private static final int EXCEPTION_MAP_CAPACITY = 32; 381 | 382 | /** 383 | * Key-value nodes for exception table. The chained hash table 384 | * uses identity comparisons, full locking, and weak references 385 | * for keys. The table has a fixed capacity because it only 386 | * maintains task exceptions long enough for joiners to access 387 | * them, so should never become very large for sustained 388 | * periods. However, since we do not know when the last joiner 389 | * completes, we must use weak references and expunge them. We do 390 | * so on each operation (hence full locking). Also, some thread in 391 | * any ForkJoinPool will call helpExpungeStaleExceptions when its 392 | * pool becomes isQuiescent. 393 | */ 394 | static final class ExceptionNode extends WeakReference> { 395 | final Throwable ex; 396 | ExceptionNode next; 397 | final long thrower; // use id not ref to avoid weak cycles 398 | ExceptionNode(ForkJoinTask task, Throwable ex, ExceptionNode next) { 399 | super(task, exceptionTableRefQueue); 400 | this.ex = ex; 401 | this.next = next; 402 | this.thrower = Thread.currentThread().getId(); 403 | } 404 | } 405 | 406 | /** 407 | * Records exception and sets status. 408 | * 409 | * @return status on exit 410 | */ 411 | final int recordExceptionalCompletion(Throwable ex) { 412 | int s; 413 | if ((s = status) >= 0) { 414 | int h = System.identityHashCode(this); 415 | final ReentrantLock lock = exceptionTableLock; 416 | lock.lock(); 417 | try { 418 | expungeStaleExceptions(); 419 | ExceptionNode[] t = exceptionTable; 420 | int i = h & (t.length - 1); 421 | for (ExceptionNode e = t[i]; ; e = e.next) { 422 | if (e == null) { 423 | t[i] = new ExceptionNode(this, ex, t[i]); 424 | break; 425 | } 426 | if (e.get() == this) // already present 427 | break; 428 | } 429 | } finally { 430 | lock.unlock(); 431 | } 432 | s = setCompletion(EXCEPTIONAL); 433 | } 434 | return s; 435 | } 436 | 437 | /** 438 | * Records exception and possibly propagates. 439 | * 440 | * @return status on exit 441 | */ 442 | private int setExceptionalCompletion(Throwable ex) { 443 | int s = recordExceptionalCompletion(ex); 444 | if ((s & DONE_MASK) == EXCEPTIONAL) 445 | internalPropagateException(ex); 446 | return s; 447 | } 448 | 449 | /** 450 | * Hook for exception propagation support for tasks with completers. 451 | */ 452 | void internalPropagateException(Throwable ex) { 453 | } 454 | 455 | /** 456 | * Cancels, ignoring any exceptions thrown by cancel. Used during 457 | * worker and pool shutdown. Cancel is spec'ed not to throw any 458 | * exceptions, but if it does anyway, we have no recourse during 459 | * shutdown, so guard against this case. 460 | */ 461 | static final void cancelIgnoringExceptions(ForkJoinTask t) { 462 | if (t != null && t.status >= 0) { 463 | try { 464 | t.cancel(false); 465 | } catch (Throwable ignore) { 466 | } 467 | } 468 | } 469 | 470 | /** 471 | * Removes exception node and clears status. 472 | */ 473 | private void clearExceptionalCompletion() { 474 | int h = System.identityHashCode(this); 475 | final ReentrantLock lock = exceptionTableLock; 476 | lock.lock(); 477 | try { 478 | ExceptionNode[] t = exceptionTable; 479 | int i = h & (t.length - 1); 480 | ExceptionNode e = t[i]; 481 | ExceptionNode pred = null; 482 | while (e != null) { 483 | ExceptionNode next = e.next; 484 | if (e.get() == this) { 485 | if (pred == null) 486 | t[i] = next; 487 | else 488 | pred.next = next; 489 | break; 490 | } 491 | pred = e; 492 | e = next; 493 | } 494 | expungeStaleExceptions(); 495 | status = 0; 496 | } finally { 497 | lock.unlock(); 498 | } 499 | } 500 | 501 | /** 502 | * Returns a rethrowable exception for the given task, if 503 | * available. To provide accurate stack traces, if the exception 504 | * was not thrown by the current thread, we try to create a new 505 | * exception of the same type as the one thrown, but with the 506 | * recorded exception as its cause. If there is no such 507 | * constructor, we instead try to use a no-arg constructor, 508 | * followed by initCause, to the same effect. If none of these 509 | * apply, or any fail due to other exceptions, we return the 510 | * recorded exception, which is still correct, although it may 511 | * contain a misleading stack trace. 512 | * 513 | * @return the exception, or null if none 514 | */ 515 | private Throwable getThrowableException() { 516 | if ((status & DONE_MASK) != EXCEPTIONAL) 517 | return null; 518 | int h = System.identityHashCode(this); 519 | ExceptionNode e; 520 | final ReentrantLock lock = exceptionTableLock; 521 | lock.lock(); 522 | try { 523 | expungeStaleExceptions(); 524 | ExceptionNode[] t = exceptionTable; 525 | e = t[h & (t.length - 1)]; 526 | while (e != null && e.get() != this) 527 | e = e.next; 528 | } finally { 529 | lock.unlock(); 530 | } 531 | Throwable ex; 532 | if (e == null || (ex = e.ex) == null) 533 | return null; 534 | if (false && e.thrower != Thread.currentThread().getId()) { 535 | Class ec = ex.getClass(); 536 | try { 537 | Constructor noArgCtor = null; 538 | Constructor[] cs = ec.getConstructors();// public ctors only 539 | for (int i = 0; i < cs.length; ++i) { 540 | Constructor c = cs[i]; 541 | Class[] ps = c.getParameterTypes(); 542 | if (ps.length == 0) 543 | noArgCtor = c; 544 | else if (ps.length == 1 && ps[0] == Throwable.class) 545 | return (Throwable)(c.newInstance(ex)); 546 | } 547 | if (noArgCtor != null) { 548 | Throwable wx = (Throwable)(noArgCtor.newInstance()); 549 | wx.initCause(ex); 550 | return wx; 551 | } 552 | } catch (Exception ignore) { 553 | } 554 | } 555 | return ex; 556 | } 557 | 558 | /** 559 | * Poll stale refs and remove them. Call only while holding lock. 560 | */ 561 | private static void expungeStaleExceptions() { 562 | for (Object x; (x = exceptionTableRefQueue.poll()) != null;) { 563 | if (x instanceof ExceptionNode) { 564 | ForkJoinTask key = ((ExceptionNode)x).get(); 565 | ExceptionNode[] t = exceptionTable; 566 | int i = System.identityHashCode(key) & (t.length - 1); 567 | ExceptionNode e = t[i]; 568 | ExceptionNode pred = null; 569 | while (e != null) { 570 | ExceptionNode next = e.next; 571 | if (e == x) { 572 | if (pred == null) 573 | t[i] = next; 574 | else 575 | pred.next = next; 576 | break; 577 | } 578 | pred = e; 579 | e = next; 580 | } 581 | } 582 | } 583 | } 584 | 585 | /** 586 | * If lock is available, poll stale refs and remove them. 587 | * Called from ForkJoinPool when pools become quiescent. 588 | */ 589 | static final void helpExpungeStaleExceptions() { 590 | final ReentrantLock lock = exceptionTableLock; 591 | if (lock.tryLock()) { 592 | try { 593 | expungeStaleExceptions(); 594 | } finally { 595 | lock.unlock(); 596 | } 597 | } 598 | } 599 | 600 | /** 601 | * A version of "sneaky throw" to relay exceptions 602 | */ 603 | static void rethrow(final Throwable ex) { 604 | if (ex != null) { 605 | if (ex instanceof Error) 606 | throw (Error)ex; 607 | if (ex instanceof RuntimeException) 608 | throw (RuntimeException)ex; 609 | ForkJoinTask.uncheckedThrow(ex); 610 | } 611 | } 612 | 613 | /** 614 | * The sneaky part of sneaky throw, relying on generics 615 | * limitations to evade compiler complaints about rethrowing 616 | * unchecked exceptions 617 | */ 618 | @SuppressWarnings("unchecked") static 619 | void uncheckedThrow(Throwable t) throws T { 620 | if (t != null) 621 | throw (T)t; // rely on vacuous cast 622 | } 623 | 624 | /** 625 | * Throws exception, if any, associated with the given status. 626 | */ 627 | private void reportException(int s) { 628 | if (s == CANCELLED) 629 | throw new CancellationException(); 630 | if (s == EXCEPTIONAL) 631 | rethrow(getThrowableException()); 632 | } 633 | 634 | // public methods 635 | 636 | /** 637 | * Arranges to asynchronously execute this task in the pool the 638 | * current task is running in, if applicable, or using the {@link 639 | * ForkJoinPool#commonPool()} if not {@link #inForkJoinPool}. While 640 | * it is not necessarily enforced, it is a usage error to fork a 641 | * task more than once unless it has completed and been 642 | * reinitialized. Subsequent modifications to the state of this 643 | * task or any data it operates on are not necessarily 644 | * consistently observable by any thread other than the one 645 | * executing it unless preceded by a call to {@link #join} or 646 | * related methods, or a call to {@link #isDone} returning {@code 647 | * true}. 648 | * 649 | * @return {@code this}, to simplify usage 650 | */ 651 | public final ForkJoinTask fork() { 652 | Thread t; 653 | if ((t = Thread.currentThread()) instanceof ForkJoinWorkerThread) 654 | ((ForkJoinWorkerThread)t).workQueue.push(this); 655 | else 656 | ForkJoinPool.common.externalPush(this); 657 | return this; 658 | } 659 | 660 | /** 661 | * Returns the result of the computation when it {@link #isDone is 662 | * done}. This method differs from {@link #get()} in that 663 | * abnormal completion results in {@code RuntimeException} or 664 | * {@code Error}, not {@code ExecutionException}, and that 665 | * interrupts of the calling thread do not cause the 666 | * method to abruptly return by throwing {@code 667 | * InterruptedException}. 668 | * 669 | * @return the computed result 670 | */ 671 | public final V join() { 672 | int s; 673 | if ((s = doJoin() & DONE_MASK) != NORMAL) 674 | reportException(s); 675 | return getRawResult(); 676 | } 677 | 678 | /** 679 | * Commences performing this task, awaits its completion if 680 | * necessary, and returns its result, or throws an (unchecked) 681 | * {@code RuntimeException} or {@code Error} if the underlying 682 | * computation did so. 683 | * 684 | * @return the computed result 685 | */ 686 | public final V invoke() { 687 | int s; 688 | if ((s = doInvoke() & DONE_MASK) != NORMAL) 689 | reportException(s); 690 | return getRawResult(); 691 | } 692 | 693 | /** 694 | * Forks the given tasks, returning when {@code isDone} holds for 695 | * each task or an (unchecked) exception is encountered, in which 696 | * case the exception is rethrown. If more than one task 697 | * encounters an exception, then this method throws any one of 698 | * these exceptions. If any task encounters an exception, the 699 | * other may be cancelled. However, the execution status of 700 | * individual tasks is not guaranteed upon exceptional return. The 701 | * status of each task may be obtained using {@link 702 | * #getException()} and related methods to check if they have been 703 | * cancelled, completed normally or exceptionally, or left 704 | * unprocessed. 705 | * 706 | * @param t1 the first task 707 | * @param t2 the second task 708 | * @throws NullPointerException if any task is null 709 | */ 710 | public static void invokeAll(ForkJoinTask t1, ForkJoinTask t2) { 711 | int s1, s2; 712 | t2.fork(); 713 | if ((s1 = t1.doInvoke() & DONE_MASK) != NORMAL) 714 | t1.reportException(s1); 715 | if ((s2 = t2.doJoin() & DONE_MASK) != NORMAL) 716 | t2.reportException(s2); 717 | } 718 | 719 | /** 720 | * Forks the given tasks, returning when {@code isDone} holds for 721 | * each task or an (unchecked) exception is encountered, in which 722 | * case the exception is rethrown. If more than one task 723 | * encounters an exception, then this method throws any one of 724 | * these exceptions. If any task encounters an exception, others 725 | * may be cancelled. However, the execution status of individual 726 | * tasks is not guaranteed upon exceptional return. The status of 727 | * each task may be obtained using {@link #getException()} and 728 | * related methods to check if they have been cancelled, completed 729 | * normally or exceptionally, or left unprocessed. 730 | * 731 | * @param tasks the tasks 732 | * @throws NullPointerException if any task is null 733 | */ 734 | public static void invokeAll(ForkJoinTask... tasks) { 735 | Throwable ex = null; 736 | int last = tasks.length - 1; 737 | for (int i = last; i >= 0; --i) { 738 | ForkJoinTask t = tasks[i]; 739 | if (t == null) { 740 | if (ex == null) 741 | ex = new NullPointerException(); 742 | } 743 | else if (i != 0) 744 | t.fork(); 745 | else if (t.doInvoke() < NORMAL && ex == null) 746 | ex = t.getException(); 747 | } 748 | for (int i = 1; i <= last; ++i) { 749 | ForkJoinTask t = tasks[i]; 750 | if (t != null) { 751 | if (ex != null) 752 | t.cancel(false); 753 | else if (t.doJoin() < NORMAL) 754 | ex = t.getException(); 755 | } 756 | } 757 | if (ex != null) 758 | rethrow(ex); 759 | } 760 | 761 | /** 762 | * Forks all tasks in the specified collection, returning when 763 | * {@code isDone} holds for each task or an (unchecked) exception 764 | * is encountered, in which case the exception is rethrown. If 765 | * more than one task encounters an exception, then this method 766 | * throws any one of these exceptions. If any task encounters an 767 | * exception, others may be cancelled. However, the execution 768 | * status of individual tasks is not guaranteed upon exceptional 769 | * return. The status of each task may be obtained using {@link 770 | * #getException()} and related methods to check if they have been 771 | * cancelled, completed normally or exceptionally, or left 772 | * unprocessed. 773 | * 774 | * @param tasks the collection of tasks 775 | * @return the tasks argument, to simplify usage 776 | * @throws NullPointerException if tasks or any element are null 777 | */ 778 | public static > Collection invokeAll(Collection tasks) { 779 | if (!(tasks instanceof RandomAccess) || !(tasks instanceof List)) { 780 | invokeAll(tasks.toArray(new ForkJoinTask[tasks.size()])); 781 | return tasks; 782 | } 783 | @SuppressWarnings("unchecked") 784 | List> ts = 785 | (List>) tasks; 786 | Throwable ex = null; 787 | int last = ts.size() - 1; 788 | for (int i = last; i >= 0; --i) { 789 | ForkJoinTask t = ts.get(i); 790 | if (t == null) { 791 | if (ex == null) 792 | ex = new NullPointerException(); 793 | } 794 | else if (i != 0) 795 | t.fork(); 796 | else if (t.doInvoke() < NORMAL && ex == null) 797 | ex = t.getException(); 798 | } 799 | for (int i = 1; i <= last; ++i) { 800 | ForkJoinTask t = ts.get(i); 801 | if (t != null) { 802 | if (ex != null) 803 | t.cancel(false); 804 | else if (t.doJoin() < NORMAL) 805 | ex = t.getException(); 806 | } 807 | } 808 | if (ex != null) 809 | rethrow(ex); 810 | return tasks; 811 | } 812 | 813 | /** 814 | * Attempts to cancel execution of this task. This attempt will 815 | * fail if the task has already completed or could not be 816 | * cancelled for some other reason. If successful, and this task 817 | * has not started when {@code cancel} is called, execution of 818 | * this task is suppressed. After this method returns 819 | * successfully, unless there is an intervening call to {@link 820 | * #reinitialize}, subsequent calls to {@link #isCancelled}, 821 | * {@link #isDone}, and {@code cancel} will return {@code true} 822 | * and calls to {@link #join} and related methods will result in 823 | * {@code CancellationException}. 824 | * 825 | *

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

This method is designed to be invoked by other 830 | * tasks. To terminate the current task, you can just return or 831 | * throw an unchecked exception from its computation method, or 832 | * invoke {@link #completeExceptionally}. 833 | * 834 | * @param mayInterruptIfRunning this value has no effect in the 835 | * default implementation because interrupts are not used to 836 | * control cancellation. 837 | * 838 | * @return {@code true} if this task is now cancelled 839 | */ 840 | public boolean cancel(boolean mayInterruptIfRunning) { 841 | return (setCompletion(CANCELLED) & DONE_MASK) == CANCELLED; 842 | } 843 | 844 | public final boolean isDone() { 845 | return status < 0; 846 | } 847 | 848 | public final boolean isCancelled() { 849 | return (status & DONE_MASK) == CANCELLED; 850 | } 851 | 852 | /** 853 | * Returns {@code true} if this task threw an exception or was cancelled. 854 | * 855 | * @return {@code true} if this task threw an exception or was cancelled 856 | */ 857 | public final boolean isCompletedAbnormally() { 858 | return status < NORMAL; 859 | } 860 | 861 | /** 862 | * Returns {@code true} if this task completed without throwing an 863 | * exception and was not cancelled. 864 | * 865 | * @return {@code true} if this task completed without throwing an 866 | * exception and was not cancelled 867 | */ 868 | public final boolean isCompletedNormally() { 869 | return (status & DONE_MASK) == NORMAL; 870 | } 871 | 872 | /** 873 | * Returns the exception thrown by the base computation, or a 874 | * {@code CancellationException} if cancelled, or {@code null} if 875 | * none or if the method has not yet completed. 876 | * 877 | * @return the exception, or {@code null} if none 878 | */ 879 | public final Throwable getException() { 880 | int s = status & DONE_MASK; 881 | return ((s >= NORMAL) ? null : 882 | (s == CANCELLED) ? new CancellationException() : 883 | getThrowableException()); 884 | } 885 | 886 | /** 887 | * Completes this task abnormally, and if not already aborted or 888 | * cancelled, causes it to throw the given exception upon 889 | * {@code join} and related operations. This method may be used 890 | * to induce exceptions in asynchronous tasks, or to force 891 | * completion of tasks that would not otherwise complete. Its use 892 | * in other situations is discouraged. This method is 893 | * overridable, but overridden versions must invoke {@code super} 894 | * implementation to maintain guarantees. 895 | * 896 | * @param ex the exception to throw. If this exception is not a 897 | * {@code RuntimeException} or {@code Error}, the actual exception 898 | * thrown will be a {@code RuntimeException} with cause {@code ex}. 899 | */ 900 | public void completeExceptionally(Throwable ex) { 901 | setExceptionalCompletion((ex instanceof RuntimeException) || 902 | (ex instanceof Error) ? ex : 903 | new RuntimeException(ex)); 904 | } 905 | 906 | /** 907 | * Completes this task, and if not already aborted or cancelled, 908 | * returning the given value as the result of subsequent 909 | * invocations of {@code join} and related operations. This method 910 | * may be used to provide results for asynchronous tasks, or to 911 | * provide alternative handling for tasks that would not otherwise 912 | * complete normally. Its use in other situations is 913 | * discouraged. This method is overridable, but overridden 914 | * versions must invoke {@code super} implementation to maintain 915 | * guarantees. 916 | * 917 | * @param value the result value for this task 918 | */ 919 | public void complete(V value) { 920 | try { 921 | setRawResult(value); 922 | } catch (Throwable rex) { 923 | setExceptionalCompletion(rex); 924 | return; 925 | } 926 | setCompletion(NORMAL); 927 | } 928 | 929 | /** 930 | * Completes this task normally without setting a value. The most 931 | * recent value established by {@link #setRawResult} (or {@code 932 | * null} by default) will be returned as the result of subsequent 933 | * invocations of {@code join} and related operations. 934 | * 935 | * @since 1.8 936 | */ 937 | public final void quietlyComplete() { 938 | setCompletion(NORMAL); 939 | } 940 | 941 | /** 942 | * Waits if necessary for the computation to complete, and then 943 | * retrieves its result. 944 | * 945 | * @return the computed result 946 | * @throws CancellationException if the computation was cancelled 947 | * @throws ExecutionException if the computation threw an 948 | * exception 949 | * @throws InterruptedException if the current thread is not a 950 | * member of a ForkJoinPool and was interrupted while waiting 951 | */ 952 | public final V get() throws InterruptedException, ExecutionException { 953 | int s = (Thread.currentThread() instanceof ForkJoinWorkerThread) ? 954 | doJoin() : externalInterruptibleAwaitDone(); 955 | Throwable ex; 956 | if ((s &= DONE_MASK) == CANCELLED) 957 | throw new CancellationException(); 958 | if (s == EXCEPTIONAL && (ex = getThrowableException()) != null) 959 | throw new ExecutionException(ex); 960 | return getRawResult(); 961 | } 962 | 963 | /** 964 | * Waits if necessary for at most the given time for the computation 965 | * to complete, and then retrieves its result, if available. 966 | * 967 | * @param timeout the maximum time to wait 968 | * @param unit the time unit of the timeout argument 969 | * @return the computed result 970 | * @throws CancellationException if the computation was cancelled 971 | * @throws ExecutionException if the computation threw an 972 | * exception 973 | * @throws InterruptedException if the current thread is not a 974 | * member of a ForkJoinPool and was interrupted while waiting 975 | * @throws TimeoutException if the wait timed out 976 | */ 977 | public final V get(long timeout, TimeUnit unit) 978 | throws InterruptedException, ExecutionException, TimeoutException { 979 | if (Thread.interrupted()) 980 | throw new InterruptedException(); 981 | // Messy in part because we measure in nanosecs, but wait in millisecs 982 | int s; long ms; 983 | long ns = unit.toNanos(timeout); 984 | if ((s = status) >= 0 && ns > 0L) { 985 | long deadline = System.nanoTime() + ns; 986 | ForkJoinPool p = null; 987 | ForkJoinPool.WorkQueue w = null; 988 | Thread t = Thread.currentThread(); 989 | if (t instanceof ForkJoinWorkerThread) { 990 | ForkJoinWorkerThread wt = (ForkJoinWorkerThread)t; 991 | p = wt.pool; 992 | w = wt.workQueue; 993 | p.helpJoinOnce(w, this); // no retries on failure 994 | } 995 | else 996 | ForkJoinPool.externalHelpJoin(this); 997 | boolean canBlock = false; 998 | boolean interrupted = false; 999 | try { 1000 | while ((s = status) >= 0) { 1001 | if (w != null && w.qlock < 0) 1002 | cancelIgnoringExceptions(this); 1003 | else if (!canBlock) { 1004 | if (p == null || p.tryCompensate()) 1005 | canBlock = true; 1006 | } 1007 | else { 1008 | if ((ms = TimeUnit.NANOSECONDS.toMillis(ns)) > 0L && 1009 | U.compareAndSwapInt(this, STATUS, s, s | SIGNAL)) { 1010 | synchronized (this) { 1011 | if (status >= 0) { 1012 | try { 1013 | wait(ms); 1014 | } catch (InterruptedException ie) { 1015 | if (p == null) 1016 | interrupted = true; 1017 | } 1018 | } 1019 | else 1020 | notifyAll(); 1021 | } 1022 | } 1023 | if ((s = status) < 0 || interrupted || 1024 | (ns = deadline - System.nanoTime()) <= 0L) 1025 | break; 1026 | } 1027 | } 1028 | } finally { 1029 | if (p != null && canBlock) 1030 | p.incrementActiveCount(); 1031 | } 1032 | if (interrupted) 1033 | throw new InterruptedException(); 1034 | } 1035 | if ((s &= DONE_MASK) != NORMAL) { 1036 | Throwable ex; 1037 | if (s == CANCELLED) 1038 | throw new CancellationException(); 1039 | if (s != EXCEPTIONAL) 1040 | throw new TimeoutException(); 1041 | if ((ex = getThrowableException()) != null) 1042 | throw new ExecutionException(ex); 1043 | } 1044 | return getRawResult(); 1045 | } 1046 | 1047 | /** 1048 | * Joins this task, without returning its result or throwing its 1049 | * exception. This method may be useful when processing 1050 | * collections of tasks when some have been cancelled or otherwise 1051 | * known to have aborted. 1052 | */ 1053 | public final void quietlyJoin() { 1054 | doJoin(); 1055 | } 1056 | 1057 | /** 1058 | * Commences performing this task and awaits its completion if 1059 | * necessary, without returning its result or throwing its 1060 | * exception. 1061 | */ 1062 | public final void quietlyInvoke() { 1063 | doInvoke(); 1064 | } 1065 | 1066 | /** 1067 | * Possibly executes tasks until the pool hosting the current task 1068 | * {@link ForkJoinPool#isQuiescent is quiescent}. This method may 1069 | * be of use in designs in which many tasks are forked, but none 1070 | * are explicitly joined, instead executing them until all are 1071 | * processed. 1072 | */ 1073 | public static void helpQuiesce() { 1074 | Thread t; 1075 | if ((t = Thread.currentThread()) instanceof ForkJoinWorkerThread) { 1076 | ForkJoinWorkerThread wt = (ForkJoinWorkerThread)t; 1077 | wt.pool.helpQuiescePool(wt.workQueue); 1078 | } 1079 | else 1080 | ForkJoinPool.quiesceCommonPool(); 1081 | } 1082 | 1083 | /** 1084 | * Resets the internal bookkeeping state of this task, allowing a 1085 | * subsequent {@code fork}. This method allows repeated reuse of 1086 | * this task, but only if reuse occurs when this task has either 1087 | * never been forked, or has been forked, then completed and all 1088 | * outstanding joins of this task have also completed. Effects 1089 | * under any other usage conditions are not guaranteed. 1090 | * This method may be useful when executing 1091 | * pre-constructed trees of subtasks in loops. 1092 | * 1093 | *

Upon completion of this method, {@code isDone()} reports 1094 | * {@code false}, and {@code getException()} reports {@code 1095 | * null}. However, the value returned by {@code getRawResult} is 1096 | * unaffected. To clear this value, you can invoke {@code 1097 | * setRawResult(null)}. 1098 | */ 1099 | public void reinitialize() { 1100 | if ((status & DONE_MASK) == EXCEPTIONAL) 1101 | clearExceptionalCompletion(); 1102 | else 1103 | status = 0; 1104 | } 1105 | 1106 | /** 1107 | * Returns the pool hosting the current task execution, or null 1108 | * if this task is executing outside of any ForkJoinPool. 1109 | * 1110 | * @see #inForkJoinPool 1111 | * @return the pool, or {@code null} if none 1112 | */ 1113 | public static ForkJoinPool getPool() { 1114 | Thread t = Thread.currentThread(); 1115 | return (t instanceof ForkJoinWorkerThread) ? 1116 | ((ForkJoinWorkerThread) t).pool : null; 1117 | } 1118 | 1119 | /** 1120 | * Returns {@code true} if the current thread is a {@link 1121 | * ForkJoinWorkerThread} executing as a ForkJoinPool computation. 1122 | * 1123 | * @return {@code true} if the current thread is a {@link 1124 | * ForkJoinWorkerThread} executing as a ForkJoinPool computation, 1125 | * or {@code false} otherwise 1126 | */ 1127 | public static boolean inForkJoinPool() { 1128 | return Thread.currentThread() instanceof ForkJoinWorkerThread; 1129 | } 1130 | 1131 | /** 1132 | * Tries to unschedule this task for execution. This method will 1133 | * typically (but is not guaranteed to) succeed if this task is 1134 | * the most recently forked task by the current thread, and has 1135 | * not commenced executing in another thread. This method may be 1136 | * useful when arranging alternative local processing of tasks 1137 | * that could have been, but were not, stolen. 1138 | * 1139 | * @return {@code true} if unforked 1140 | */ 1141 | public boolean tryUnfork() { 1142 | Thread t; 1143 | return (((t = Thread.currentThread()) instanceof ForkJoinWorkerThread) ? 1144 | ((ForkJoinWorkerThread)t).workQueue.tryUnpush(this) : 1145 | ForkJoinPool.tryExternalUnpush(this)); 1146 | } 1147 | 1148 | /** 1149 | * Returns an estimate of the number of tasks that have been 1150 | * forked by the current worker thread but not yet executed. This 1151 | * value may be useful for heuristic decisions about whether to 1152 | * fork other tasks. 1153 | * 1154 | * @return the number of tasks 1155 | */ 1156 | public static int getQueuedTaskCount() { 1157 | Thread t; ForkJoinPool.WorkQueue q; 1158 | if ((t = Thread.currentThread()) instanceof ForkJoinWorkerThread) 1159 | q = ((ForkJoinWorkerThread)t).workQueue; 1160 | else 1161 | q = ForkJoinPool.commonSubmitterQueue(); 1162 | return (q == null) ? 0 : q.queueSize(); 1163 | } 1164 | 1165 | /** 1166 | * Returns an estimate of how many more locally queued tasks are 1167 | * held by the current worker thread than there are other worker 1168 | * threads that might steal them, or zero if this thread is not 1169 | * operating in a ForkJoinPool. This value may be useful for 1170 | * heuristic decisions about whether to fork other tasks. In many 1171 | * usages of ForkJoinTasks, at steady state, each worker should 1172 | * aim to maintain a small constant surplus (for example, 3) of 1173 | * tasks, and to process computations locally if this threshold is 1174 | * exceeded. 1175 | * 1176 | * @return the surplus number of tasks, which may be negative 1177 | */ 1178 | public static int getSurplusQueuedTaskCount() { 1179 | return ForkJoinPool.getSurplusQueuedTaskCount(); 1180 | } 1181 | 1182 | // Extension methods 1183 | 1184 | /** 1185 | * Returns the result that would be returned by {@link #join}, even 1186 | * if this task completed abnormally, or {@code null} if this task 1187 | * is not known to have been completed. This method is designed 1188 | * to aid debugging, as well as to support extensions. Its use in 1189 | * any other context is discouraged. 1190 | * 1191 | * @return the result, or {@code null} if not completed 1192 | */ 1193 | public abstract V getRawResult(); 1194 | 1195 | /** 1196 | * Forces the given value to be returned as a result. This method 1197 | * is designed to support extensions, and should not in general be 1198 | * called otherwise. 1199 | * 1200 | * @param value the value 1201 | */ 1202 | protected abstract void setRawResult(V value); 1203 | 1204 | /** 1205 | * Immediately performs the base action of this task and returns 1206 | * true if, upon return from this method, this task is guaranteed 1207 | * to have completed normally. This method may return false 1208 | * otherwise, to indicate that this task is not necessarily 1209 | * complete (or is not known to be complete), for example in 1210 | * asynchronous actions that require explicit invocations of 1211 | * completion methods. This method may also throw an (unchecked) 1212 | * exception to indicate abnormal exit. This method is designed to 1213 | * support extensions, and should not in general be called 1214 | * otherwise. 1215 | * 1216 | * @return {@code true} if this task is known to have completed normally 1217 | */ 1218 | protected abstract boolean exec(); 1219 | 1220 | /** 1221 | * Returns, but does not unschedule or execute, a task queued by 1222 | * the current thread but not yet executed, if one is immediately 1223 | * available. There is no guarantee that this task will actually 1224 | * be polled or executed next. Conversely, this method may return 1225 | * null even if a task exists but cannot be accessed without 1226 | * contention with other threads. This method is designed 1227 | * primarily to support extensions, and is unlikely to be useful 1228 | * otherwise. 1229 | * 1230 | * @return the next task, or {@code null} if none are available 1231 | */ 1232 | protected static ForkJoinTask peekNextLocalTask() { 1233 | Thread t; ForkJoinPool.WorkQueue q; 1234 | if ((t = Thread.currentThread()) instanceof ForkJoinWorkerThread) 1235 | q = ((ForkJoinWorkerThread)t).workQueue; 1236 | else 1237 | q = ForkJoinPool.commonSubmitterQueue(); 1238 | return (q == null) ? null : q.peek(); 1239 | } 1240 | 1241 | /** 1242 | * Unschedules and returns, without executing, the next task 1243 | * queued by the current thread but not yet executed, if the 1244 | * current thread is operating in a ForkJoinPool. This method is 1245 | * designed primarily to support extensions, and is unlikely to be 1246 | * useful otherwise. 1247 | * 1248 | * @return the next task, or {@code null} if none are available 1249 | */ 1250 | protected static ForkJoinTask pollNextLocalTask() { 1251 | Thread t; 1252 | return ((t = Thread.currentThread()) instanceof ForkJoinWorkerThread) ? 1253 | ((ForkJoinWorkerThread)t).workQueue.nextLocalTask() : 1254 | null; 1255 | } 1256 | 1257 | /** 1258 | * If the current thread is operating in a ForkJoinPool, 1259 | * unschedules and returns, without executing, the next task 1260 | * queued by the current thread but not yet executed, if one is 1261 | * available, or if not available, a task that was forked by some 1262 | * other thread, if available. Availability may be transient, so a 1263 | * {@code null} result does not necessarily imply quiescence of 1264 | * the pool this task is operating in. This method is designed 1265 | * primarily to support extensions, and is unlikely to be useful 1266 | * otherwise. 1267 | * 1268 | * @return a task, or {@code null} if none are available 1269 | */ 1270 | protected static ForkJoinTask pollTask() { 1271 | Thread t; ForkJoinWorkerThread wt; 1272 | return ((t = Thread.currentThread()) instanceof ForkJoinWorkerThread) ? 1273 | (wt = (ForkJoinWorkerThread)t).pool.nextTaskFor(wt.workQueue) : 1274 | null; 1275 | } 1276 | 1277 | // tag operations 1278 | 1279 | /** 1280 | * Returns the tag for this task. 1281 | * 1282 | * @return the tag for this task 1283 | * @since 1.8 1284 | */ 1285 | public final short getForkJoinTaskTag() { 1286 | return (short)status; 1287 | } 1288 | 1289 | /** 1290 | * Atomically sets the tag value for this task. 1291 | * 1292 | * @param tag the tag value 1293 | * @return the previous value of the tag 1294 | * @since 1.8 1295 | */ 1296 | public final short setForkJoinTaskTag(short tag) { 1297 | for (int s;;) { 1298 | if (U.compareAndSwapInt(this, STATUS, s = status, 1299 | (s & ~SMASK) | (tag & SMASK))) 1300 | return (short)s; 1301 | } 1302 | } 1303 | 1304 | /** 1305 | * Atomically conditionally sets the tag value for this task. 1306 | * Among other applications, tags can be used as visit markers 1307 | * in tasks operating on graphs, as in methods that check: {@code 1308 | * if (task.compareAndSetForkJoinTaskTag((short)0, (short)1))} 1309 | * before processing, otherwise exiting because the node has 1310 | * already been visited. 1311 | * 1312 | * @param e the expected tag value 1313 | * @param tag the new tag value 1314 | * @return true if successful; i.e., the current value was 1315 | * equal to e and is now tag. 1316 | * @since 1.8 1317 | */ 1318 | public final boolean compareAndSetForkJoinTaskTag(short e, short tag) { 1319 | for (int s;;) { 1320 | if ((short)(s = status) != e) 1321 | return false; 1322 | if (U.compareAndSwapInt(this, STATUS, s, 1323 | (s & ~SMASK) | (tag & SMASK))) 1324 | return true; 1325 | } 1326 | } 1327 | 1328 | /** 1329 | * Adaptor for Runnables. This implements RunnableFuture 1330 | * to be compliant with AbstractExecutorService constraints 1331 | * when used in ForkJoinPool. 1332 | */ 1333 | static final class AdaptedRunnable extends ForkJoinTask 1334 | implements RunnableFuture { 1335 | final Runnable runnable; 1336 | T result; 1337 | AdaptedRunnable(Runnable runnable, T result) { 1338 | if (runnable == null) throw new NullPointerException(); 1339 | this.runnable = runnable; 1340 | this.result = result; // OK to set this even before completion 1341 | } 1342 | public final T getRawResult() { return result; } 1343 | public final void setRawResult(T v) { result = v; } 1344 | public final boolean exec() { runnable.run(); return true; } 1345 | public final void run() { invoke(); } 1346 | private static final long serialVersionUID = 5232453952276885070L; 1347 | } 1348 | 1349 | /** 1350 | * Adaptor for Runnables without results 1351 | */ 1352 | static final class AdaptedRunnableAction extends ForkJoinTask 1353 | implements RunnableFuture { 1354 | final Runnable runnable; 1355 | AdaptedRunnableAction(Runnable runnable) { 1356 | if (runnable == null) throw new NullPointerException(); 1357 | this.runnable = runnable; 1358 | } 1359 | public final Void getRawResult() { return null; } 1360 | public final void setRawResult(Void v) { } 1361 | public final boolean exec() { runnable.run(); return true; } 1362 | public final void run() { invoke(); } 1363 | private static final long serialVersionUID = 5232453952276885070L; 1364 | } 1365 | 1366 | /** 1367 | * Adaptor for Callables 1368 | */ 1369 | static final class AdaptedCallable extends ForkJoinTask 1370 | implements RunnableFuture { 1371 | final Callable callable; 1372 | T result; 1373 | AdaptedCallable(Callable callable) { 1374 | if (callable == null) throw new NullPointerException(); 1375 | this.callable = callable; 1376 | } 1377 | public final T getRawResult() { return result; } 1378 | public final void setRawResult(T v) { result = v; } 1379 | public final boolean exec() { 1380 | try { 1381 | result = callable.call(); 1382 | return true; 1383 | } catch (Error err) { 1384 | throw err; 1385 | } catch (RuntimeException rex) { 1386 | throw rex; 1387 | } catch (Exception ex) { 1388 | throw new RuntimeException(ex); 1389 | } 1390 | } 1391 | public final void run() { invoke(); } 1392 | private static final long serialVersionUID = 2838392045355241008L; 1393 | } 1394 | 1395 | /** 1396 | * Returns a new {@code ForkJoinTask} that performs the {@code run} 1397 | * method of the given {@code Runnable} as its action, and returns 1398 | * a null result upon {@link #join}. 1399 | * 1400 | * @param runnable the runnable action 1401 | * @return the task 1402 | */ 1403 | public static ForkJoinTask adapt(Runnable runnable) { 1404 | return new AdaptedRunnableAction(runnable); 1405 | } 1406 | 1407 | /** 1408 | * Returns a new {@code ForkJoinTask} that performs the {@code run} 1409 | * method of the given {@code Runnable} as its action, and returns 1410 | * the given result upon {@link #join}. 1411 | * 1412 | * @param runnable the runnable action 1413 | * @param result the result upon completion 1414 | * @return the task 1415 | */ 1416 | public static ForkJoinTask adapt(Runnable runnable, T result) { 1417 | return new AdaptedRunnable(runnable, result); 1418 | } 1419 | 1420 | /** 1421 | * Returns a new {@code ForkJoinTask} that performs the {@code call} 1422 | * method of the given {@code Callable} as its action, and returns 1423 | * its result upon {@link #join}, translating any checked exceptions 1424 | * encountered into {@code RuntimeException}. 1425 | * 1426 | * @param callable the callable action 1427 | * @return the task 1428 | */ 1429 | public static ForkJoinTask adapt(Callable callable) { 1430 | return new AdaptedCallable(callable); 1431 | } 1432 | 1433 | // Serialization support 1434 | 1435 | private static final long serialVersionUID = -7721805057305804111L; 1436 | 1437 | /** 1438 | * Saves this task to a stream (that is, serializes it). 1439 | * 1440 | * @serialData the current run status and the exception thrown 1441 | * during execution, or {@code null} if none 1442 | */ 1443 | private void writeObject(java.io.ObjectOutputStream s) 1444 | throws java.io.IOException { 1445 | s.defaultWriteObject(); 1446 | s.writeObject(getException()); 1447 | } 1448 | 1449 | /** 1450 | * Reconstitutes this task from a stream (that is, deserializes it). 1451 | */ 1452 | private void readObject(java.io.ObjectInputStream s) 1453 | throws java.io.IOException, ClassNotFoundException { 1454 | s.defaultReadObject(); 1455 | Object ex = s.readObject(); 1456 | if (ex != null) 1457 | setExceptionalCompletion((Throwable)ex); 1458 | } 1459 | 1460 | // Unsafe mechanics 1461 | private static final sun.misc.Unsafe U; 1462 | private static final long STATUS; 1463 | 1464 | static { 1465 | exceptionTableLock = new ReentrantLock(); 1466 | exceptionTableRefQueue = new ReferenceQueue(); 1467 | exceptionTable = new ExceptionNode[EXCEPTION_MAP_CAPACITY]; 1468 | try { 1469 | U = getUnsafe(); 1470 | Class k = ForkJoinTask.class; 1471 | STATUS = U.objectFieldOffset 1472 | (k.getDeclaredField("status")); 1473 | } catch (Exception e) { 1474 | throw new Error(e); 1475 | } 1476 | } 1477 | 1478 | /** 1479 | * Returns a sun.misc.Unsafe. Suitable for use in a 3rd party package. 1480 | * Replace with a simple call to Unsafe.getUnsafe when integrating 1481 | * into a jdk. 1482 | * 1483 | * @return a sun.misc.Unsafe 1484 | */ 1485 | private static sun.misc.Unsafe getUnsafe() { 1486 | return monix.forkJoin.Unsafe.instance; 1487 | } 1488 | } 1489 | --------------------------------------------------------------------------------