From fa8012d28687986902ce1255a19f9f49affb3bca Mon Sep 17 00:00:00 2001 From: Adriaan Moors Date: Tue, 14 Jul 2015 15:00:49 -0700 Subject: Remove our fork of forkjoin. Java 8 bundles it. Provide deprecated compatibility stubs for the types and static members, which forward as follows: ``` scala.concurrent.forkjoin.ForkJoinPool => java.util.concurrent.ForkJoinPool scala.concurrent.forkjoin.ForkJoinTask => java.util.concurrent.ForkJoinTask scala.concurrent.forkjoin.ForkJoinWorkerThread => java.util.concurrent.ForkJoinWorkerThread scala.concurrent.forkjoin.LinkedTransferQueue => java.util.concurrent.LinkedTransferQueue scala.concurrent.forkjoin.RecursiveAction => java.util.concurrent.RecursiveAction scala.concurrent.forkjoin.RecursiveTask => java.util.concurrent.RecursiveTask scala.concurrent.forkjoin.ThreadLocalRandom => java.util.concurrent.ThreadLocalRandom ``` To prepare for Java 9, the Scala library does not itself use `sun.misc.Unsafe`. However, for now, it provide a convenience accessor for it via `scala.concurrent.util.Unsafe`. This (deprecated) class will be removed as soon as the eco-system drops its use (akka-actor, I'm looking at you). --- .../scala/collection/concurrent/TrieMap.scala | 2 +- .../collection/parallel/ParIterableLike.scala | 2 +- .../scala/collection/parallel/TaskSupport.scala | 4 +- src/library/scala/collection/parallel/Tasks.scala | 2 +- .../scala/concurrent/forkjoin/package.scala | 60 ++++++++++++++++++++++ .../concurrent/impl/ExecutionContextImpl.scala | 3 +- src/library/scala/concurrent/util/Unsafe.java | 38 ++++++++++++++ 7 files changed, 104 insertions(+), 7 deletions(-) create mode 100644 src/library/scala/concurrent/forkjoin/package.scala create mode 100644 src/library/scala/concurrent/util/Unsafe.java (limited to 'src/library') diff --git a/src/library/scala/collection/concurrent/TrieMap.scala b/src/library/scala/collection/concurrent/TrieMap.scala index bcfea7a463..74e0e0f7d2 100644 --- a/src/library/scala/collection/concurrent/TrieMap.scala +++ b/src/library/scala/collection/concurrent/TrieMap.scala @@ -471,7 +471,7 @@ private[collection] final class CNode[K, V](val bitmap: Int, val array: Array[Ba val offset = if (array.length > 0) //util.Random.nextInt(array.length) /* <-- benchmarks show that this causes observable contention */ - scala.concurrent.forkjoin.ThreadLocalRandom.current.nextInt(0, array.length) + java.util.concurrent.ThreadLocalRandom.current.nextInt(0, array.length) else 0 while (i < array.length) { val pos = (i + offset) % array.length diff --git a/src/library/scala/collection/parallel/ParIterableLike.scala b/src/library/scala/collection/parallel/ParIterableLike.scala index 016255dca4..53f9a7b87a 100644 --- a/src/library/scala/collection/parallel/ParIterableLike.scala +++ b/src/library/scala/collection/parallel/ParIterableLike.scala @@ -195,7 +195,7 @@ self: ParIterableLike[T, Repr, Sequential] => * import scala.collection.parallel._ * val pc = mutable.ParArray(1, 2, 3) * pc.tasksupport = new ForkJoinTaskSupport( - * new scala.concurrent.forkjoin.ForkJoinPool(2)) + * new java.util.concurrent.ForkJoinPool(2)) * }}} * * @see [[scala.collection.parallel.TaskSupport]] diff --git a/src/library/scala/collection/parallel/TaskSupport.scala b/src/library/scala/collection/parallel/TaskSupport.scala index 9064018d46..6ab694de04 100644 --- a/src/library/scala/collection/parallel/TaskSupport.scala +++ b/src/library/scala/collection/parallel/TaskSupport.scala @@ -10,7 +10,7 @@ package scala package collection.parallel import java.util.concurrent.ThreadPoolExecutor -import scala.concurrent.forkjoin.ForkJoinPool +import java.util.concurrent.ForkJoinPool import scala.concurrent.ExecutionContext /** A trait implementing the scheduling of a parallel collection operation. @@ -41,7 +41,7 @@ import scala.concurrent.ExecutionContext * import scala.collection.parallel._ * val pc = mutable.ParArray(1, 2, 3) * pc.tasksupport = new ForkJoinTaskSupport( - * new scala.concurrent.forkjoin.ForkJoinPool(2)) + * new java.util.concurrent.ForkJoinPool(2)) * }}} * * @see [[http://docs.scala-lang.org/overviews/parallel-collections/configuration.html Configuring Parallel Collections]] section diff --git a/src/library/scala/collection/parallel/Tasks.scala b/src/library/scala/collection/parallel/Tasks.scala index fcf0dff846..c9a75752df 100644 --- a/src/library/scala/collection/parallel/Tasks.scala +++ b/src/library/scala/collection/parallel/Tasks.scala @@ -10,7 +10,7 @@ package scala package collection.parallel import java.util.concurrent.ThreadPoolExecutor -import scala.concurrent.forkjoin._ +import java.util.concurrent.{ForkJoinPool, RecursiveAction, ForkJoinWorkerThread} import scala.concurrent.ExecutionContext import scala.util.control.Breaks._ import scala.annotation.unchecked.uncheckedVariance diff --git a/src/library/scala/concurrent/forkjoin/package.scala b/src/library/scala/concurrent/forkjoin/package.scala new file mode 100644 index 0000000000..7f4524fccf --- /dev/null +++ b/src/library/scala/concurrent/forkjoin/package.scala @@ -0,0 +1,60 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2015, LAMP/EPFL and Typesafe, Inc. ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +package scala.concurrent +import java.util.{concurrent => juc} +import java.util.Collection + +package object forkjoin { + @deprecated("Use java.util.concurrent.ForkJoinPool directly, instead of this alias.", "2.12.0") + type ForkJoinPool = juc.ForkJoinPool + @deprecated("Use java.util.concurrent.ForkJoinPool directly, instead of this alias.", "2.12.0") + object ForkJoinPool { + type ForkJoinWorkerThreadFactory = juc.ForkJoinPool.ForkJoinWorkerThreadFactory + type ManagedBlocker = juc.ForkJoinPool.ManagedBlocker + + val defaultForkJoinWorkerThreadFactory: ForkJoinWorkerThreadFactory = juc.ForkJoinPool.defaultForkJoinWorkerThreadFactory + def managedBlock(blocker: ManagedBlocker): Unit = juc.ForkJoinPool.managedBlock(blocker) + } + + @deprecated("Use java.util.concurrent.ForkJoinTask directly, instead of this alias.", "2.12.0") + type ForkJoinTask[T] = juc.ForkJoinTask[T] + @deprecated("Use java.util.concurrent.ForkJoinTask directly, instead of this alias.", "2.12.0") + object ForkJoinTask { + def adapt(runnable: Runnable): ForkJoinTask[_] = juc.ForkJoinTask.adapt(runnable) + def adapt[T](callable: juc.Callable[_ <: T]): ForkJoinTask[T] = juc.ForkJoinTask.adapt(callable) + def adapt[T](runnable: Runnable, result: T): ForkJoinTask[T] = juc.ForkJoinTask.adapt(runnable, result) + def getPool(): ForkJoinPool = juc.ForkJoinTask.getPool + def getQueuedTaskCount(): Int = juc.ForkJoinTask.getQueuedTaskCount + def getSurplusQueuedTaskCount(): Int = juc.ForkJoinTask.getSurplusQueuedTaskCount + def helpQuiesce(): Unit = juc.ForkJoinTask.helpQuiesce + def inForkJoinPool(): Boolean = juc.ForkJoinTask.inForkJoinPool + def invokeAll[T <: ForkJoinTask[_]](tasks: Collection[T]): Collection[T] = juc.ForkJoinTask.invokeAll(tasks) + def invokeAll[T](t1: ForkJoinTask[T]): Unit = juc.ForkJoinTask.invokeAll(t1) + def invokeAll[T](tasks: ForkJoinTask[T]*): Unit = juc.ForkJoinTask.invokeAll(tasks: _*) + } + + @deprecated("Use java.util.concurrent.ForkJoinWorkerThread directly, instead of this alias.", "2.12.0") + type ForkJoinWorkerThread = juc.ForkJoinWorkerThread + @deprecated("Use java.util.concurrent.LinkedTransferQueue directly, instead of this alias.", "2.12.0") + type LinkedTransferQueue[T] = juc.LinkedTransferQueue[T] + @deprecated("Use java.util.concurrent.RecursiveAction directly, instead of this alias.", "2.12.0") + type RecursiveAction = juc.RecursiveAction + @deprecated("Use java.util.concurrent.RecursiveTask directly, instead of this alias.", "2.12.0") + type RecursiveTask[T] = juc.RecursiveTask[T] + + @deprecated("Use java.util.concurrent.ThreadLocalRandom directly, instead of this alias.", "2.12.0") + type ThreadLocalRandom = juc.ThreadLocalRandom + @deprecated("Use java.util.concurrent.ThreadLocalRandom directly, instead of this alias.", "2.12.0") + object ThreadLocalRandom { + // For source compatibility, current must declare the empty argument list. + // Having no argument list makes more sense since it doesn't have any side effects, + // but existing callers will break if they invoked it as `current()`. + def current() = juc.ThreadLocalRandom.current + } +} diff --git a/src/library/scala/concurrent/impl/ExecutionContextImpl.scala b/src/library/scala/concurrent/impl/ExecutionContextImpl.scala index 0c7f98ce5a..c98746a98d 100644 --- a/src/library/scala/concurrent/impl/ExecutionContextImpl.scala +++ b/src/library/scala/concurrent/impl/ExecutionContextImpl.scala @@ -10,10 +10,9 @@ package scala.concurrent.impl -import java.util.concurrent.{ LinkedBlockingQueue, Callable, Executor, ExecutorService, Executors, ThreadFactory, TimeUnit, ThreadPoolExecutor } +import java.util.concurrent.{ ForkJoinPool, ForkJoinWorkerThread, ForkJoinTask, LinkedBlockingQueue, Callable, Executor, ExecutorService, Executors, ThreadFactory, TimeUnit, ThreadPoolExecutor } import java.util.concurrent.atomic.AtomicInteger import java.util.Collection -import scala.concurrent.forkjoin._ import scala.concurrent.{ BlockContext, ExecutionContext, Awaitable, CanAwait, ExecutionContextExecutor, ExecutionContextExecutorService } import scala.util.control.NonFatal import scala.annotation.tailrec diff --git a/src/library/scala/concurrent/util/Unsafe.java b/src/library/scala/concurrent/util/Unsafe.java new file mode 100644 index 0000000000..73739e377d --- /dev/null +++ b/src/library/scala/concurrent/util/Unsafe.java @@ -0,0 +1,38 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +package scala.concurrent.util; +import java.lang.reflect.Field; + +// TODO: remove once akka no longer needs it, hopefully by 2.12.0-M3! +@Deprecated +public final class Unsafe { + @Deprecated + public final static sun.misc.Unsafe instance; + static { + try { + sun.misc.Unsafe found = null; + for(Field field : sun.misc.Unsafe.class.getDeclaredFields()) { + if (field.getType() == sun.misc.Unsafe.class) { + field.setAccessible(true); + found = (sun.misc.Unsafe) field.get(null); + break; + } + } + if (found == null) throw new IllegalStateException("Can't find instance of sun.misc.Unsafe"); + else instance = found; + } catch(Throwable t) { + throw new ExceptionInInitializerError(t); + } + } +} + +// Scala version: +// classOf[sun.misc.Unsafe].getDeclaredFields.filter(_.getType == classOf[sun.misc.Unsafe]).headOption.map { field => +// field.setAccessible(true); field.get(null).asInstanceOf[sun.misc.Unsafe] +// } getOrElse (throw new IllegalStateException("Can't find instance of sun.misc.Unsafe")) -- cgit v1.2.3