diff options
-rw-r--r-- | src/library/scala/collection/JavaConverters.scala | 12 | ||||
-rw-r--r-- | src/library/scala/collection/mutable/ListBuffer.scala | 4 | ||||
-rw-r--r-- | src/library/scala/concurrent/ExecutionContext.scala | 42 | ||||
-rw-r--r-- | src/library/scala/concurrent/package.scala | 43 | ||||
-rw-r--r-- | src/scalap/scala/tools/scalap/Classfile.scala | 6 | ||||
-rw-r--r-- | src/scalap/scala/tools/scalap/Classfiles.scala | 8 |
6 files changed, 82 insertions, 33 deletions
diff --git a/src/library/scala/collection/JavaConverters.scala b/src/library/scala/collection/JavaConverters.scala index d48a1764e9..2337f0ef84 100644 --- a/src/library/scala/collection/JavaConverters.scala +++ b/src/library/scala/collection/JavaConverters.scala @@ -18,12 +18,12 @@ import convert._ * * The following conversions are supported via `asScala` and `asJava`: *{{{ - * scala.collection.Iterable <=> java.lang.Iterable - * scala.collection.Iterator <=> java.util.Iterator - * scala.collection.mutable.Buffer <=> java.util.List - * scala.collection.mutable.Set <=> java.util.Set - * scala.collection.mutable.Map <=> java.util.Map - * scala.collection.mutable.concurrent.Map <=> java.util.concurrent.ConcurrentMap + * scala.collection.Iterable <=> java.lang.Iterable + * scala.collection.Iterator <=> java.util.Iterator + * scala.collection.mutable.Buffer <=> java.util.List + * scala.collection.mutable.Set <=> java.util.Set + * scala.collection.mutable.Map <=> java.util.Map + * scala.collection.concurrent.Map <=> java.util.concurrent.ConcurrentMap *}}} * The following conversions are supported via `asScala` and through * specially-named extension methods to convert to Java collections, as shown: diff --git a/src/library/scala/collection/mutable/ListBuffer.scala b/src/library/scala/collection/mutable/ListBuffer.scala index 3bb7004184..aa79e972d5 100644 --- a/src/library/scala/collection/mutable/ListBuffer.scala +++ b/src/library/scala/collection/mutable/ListBuffer.scala @@ -119,6 +119,10 @@ final class ListBuffer[A] // Don't use the inherited size, which forwards to a List and is O(n). override def size = length + // Override with efficient implementations using the extra size information available to ListBuffer. + override def isEmpty: Boolean = len == 0 + override def nonEmpty: Boolean = len > 0 + // Implementations of abstract methods in Buffer override def apply(n: Int): A = diff --git a/src/library/scala/concurrent/ExecutionContext.scala b/src/library/scala/concurrent/ExecutionContext.scala index fe684e4d46..f46f294387 100644 --- a/src/library/scala/concurrent/ExecutionContext.scala +++ b/src/library/scala/concurrent/ExecutionContext.scala @@ -25,21 +25,20 @@ import scala.annotation.implicitNotFound * and an implicit `ExecutionContext`. The implicit `ExecutionContext` * will be used to execute the callback. * - * It is possible to simply import + * While it is possible to simply import * `scala.concurrent.ExecutionContext.Implicits.global` to obtain an - * implicit `ExecutionContext`. This global context is a reasonable - * default thread pool. - * - * However, application developers should carefully consider where they - * want to set policy; ideally, one place per application (or per - * logically-related section of code) will make a decision about - * which `ExecutionContext` to use. That is, you might want to avoid - * hardcoding `scala.concurrent.ExecutionContext.Implicits.global` all - * over the place in your code. - * One approach is to add `(implicit ec: ExecutionContext)` - * to methods which need an `ExecutionContext`. Then import a specific - * context in one place for the entire application or module, - * passing it implicitly to individual methods. + * implicit `ExecutionContext`, application developers should carefully + * consider where they want to set execution policy; + * ideally, one place per application—or per logically related section of code— + * will make a decision about which `ExecutionContext` to use. + * That is, you will mostly want to avoid hardcoding, especially via an import, + * `scala.concurrent.ExecutionContext.Implicits.global`. + * The recommended approach is to add `(implicit ec: ExecutionContext)` to methods, + * or class constructor parameters, which need an `ExecutionContext`. + * + * Then locally import a specific `ExecutionContext` in one place for the entire + * application or module, passing it implicitly to individual methods. + * Alternatively define a local implicit val with the required `ExecutionContext`. * * A custom `ExecutionContext` may be appropriate to execute code * which blocks on IO or performs long-running computations. @@ -111,9 +110,18 @@ object ExecutionContext { * The explicit global `ExecutionContext`. Invoke `global` when you want to provide the global * `ExecutionContext` explicitly. * - * The default `ExecutionContext` implementation is backed by a work-stealing thread pool. By default, - * the thread pool uses a target number of worker threads equal to the number of - * [[https://docs.oracle.com/javase/8/docs/api/java/lang/Runtime.html#availableProcessors-- available processors]]. + * The default `ExecutionContext` implementation is backed by a work-stealing thread pool. + * It can be configured via the following [[scala.sys.SystemProperties]]: + * + * `scala.concurrent.context.minThreads` = defaults to "1" + * `scala.concurrent.context.numThreads` = defaults to "x1" (i.e. the current number of available processors * 1) + * `scala.concurrent.context.maxThreads` = defaults to "x1" (i.e. the current number of available processors * 1) + * `scala.concurrent.context.maxExtraThreads` = defaults to "256" + * + * The pool size of threads is then `numThreads` bounded by `minThreads` on the lower end and `maxThreads` on the high end. + * + * The `maxExtraThreads` is the maximum number of extra threads to have at any given time to evade deadlock, + * see [[scala.concurrent.BlockContext]]. * * @return the global `ExecutionContext` */ diff --git a/src/library/scala/concurrent/package.scala b/src/library/scala/concurrent/package.scala index 667a7547ac..0695ee3351 100644 --- a/src/library/scala/concurrent/package.scala +++ b/src/library/scala/concurrent/package.scala @@ -22,12 +22,31 @@ import scala.annotation.implicitNotFound * == Common Imports == * * When working with Futures, you will often find that importing the whole concurrent - * package is convenient, furthermore you are likely to need an implicit ExecutionContext - * in scope for many operations involving Futures and Promises: + * package is convenient: * * {{{ * import scala.concurrent._ - * import ExecutionContext.Implicits.global + * }}} + * + * When using things like `Future`s, it is often required to have an implicit `ExecutionContext` + * in scope. The general advice for these implicits are as follows. + * + * If the code in question is a class or method definition, and no `ExecutionContext` is available, + * request one from the caller by adding an implicit parameter list: + * + * {{{ + * def myMethod(myParam: MyType)(implicit ec: ExecutionContext) = … + * //Or + * class MyClass(myParam: MyType)(implicit ec: ExecutionContext) { … } + * }}} + * + * This allows the caller of the method, or creator of the instance of the class, to decide which + * `ExecutionContext` should be used. + * + * For typical REPL usage and experimentation, importing the global `ExecutionContext` is often desired. + * + * {{{ + * import scala.concurrent.ExcutionContext.Implicits.global * }}} * * == Specifying Durations == @@ -140,17 +159,20 @@ package concurrent { /** * `Await` is what is used to ensure proper handling of blocking for `Awaitable` instances. * - * While occasionally useful, e.g. for testing, it is recommended that you avoid Await - * when possible in favor of callbacks and combinators like onComplete and use in - * for comprehensions. Await will block the thread on which it runs, and could cause - * performance and deadlock issues. + * While occasionally useful, e.g. for testing, it is recommended that you avoid Await whenever possible— + * instead favoring combinators and/or callbacks. + * Await's `result` and `ready` methods will block the calling thread's execution until they return, + * which will cause performance degradation, and possibly, deadlock issues. */ object Await { /** * Await the "completed" state of an `Awaitable`. * * Although this method is blocking, the internal use of [[scala.concurrent.blocking blocking]] ensures that - * the underlying [[ExecutionContext]] is prepared to properly manage the blocking. + * the underlying [[ExecutionContext]] is given an opportunity to properly manage the blocking. + * + * WARNING: It is strongly discouraged to supply lengthy timeouts since the progress of the calling thread will be + * suspended—blocked—until either the `Awaitable` becomes ready or the timeout expires. * * @param awaitable * the `Awaitable` to be awaited @@ -172,7 +194,10 @@ package concurrent { * Await and return the result (of type `T`) of an `Awaitable`. * * Although this method is blocking, the internal use of [[scala.concurrent.blocking blocking]] ensures that - * the underlying [[ExecutionContext]] to properly detect blocking and ensure that there are no deadlocks. + * the underlying [[ExecutionContext]] is given an opportunity to properly manage the blocking. + * + * WARNING: It is strongly discouraged to supply lengthy timeouts since the progress of the calling thread will be + * suspended—blocked—until either the `Awaitable` has a result or the timeout expires. * * @param awaitable * the `Awaitable` to be awaited diff --git a/src/scalap/scala/tools/scalap/Classfile.scala b/src/scalap/scala/tools/scalap/Classfile.scala index f62df285f9..9549097ca6 100644 --- a/src/scalap/scala/tools/scalap/Classfile.scala +++ b/src/scalap/scala/tools/scalap/Classfile.scala @@ -79,6 +79,9 @@ class Classfile(in: ByteArrayReader) { case class DoubleConst(x: Double) extends PoolEntry(CONSTANT_DOUBLE) case class NameAndType(nameId: Int, typeId: Int) extends PoolEntry(CONSTANT_NAMEANDTYPE) case object Empty extends PoolEntry(0) { } + case class MethodHandle(kindId: Int, refId: Int) extends PoolEntry(CONSTANT_METHODHANDLE) + case class InvokeDynamic(bootMethodId: Int, nameTypeId: Int) extends PoolEntry(CONSTANT_INVDYNAMIC) + case class MethodType(descId: Int) extends PoolEntry(CONSTANT_METHODTYPE) val entries = { val pool = new Array[PoolEntry](in.nextChar.toInt) @@ -102,6 +105,9 @@ class Classfile(in: ByteArrayReader) { case CONSTANT_NAMEANDTYPE => NameAndType(in.nextChar, in.nextChar) case CONSTANT_INTEGER => IntegerConst(in.nextInt) case CONSTANT_FLOAT => FloatConst(in.nextFloat) + case CONSTANT_METHODHANDLE => MethodHandle(in.nextByte, in.nextChar) + case CONSTANT_METHODTYPE => MethodType(in.nextChar) + case CONSTANT_INVDYNAMIC => InvokeDynamic(in.nextChar, in.nextChar) } i += 1 diff --git a/src/scalap/scala/tools/scalap/Classfiles.scala b/src/scalap/scala/tools/scalap/Classfiles.scala index 9295dd7aff..c228b747c8 100644 --- a/src/scalap/scala/tools/scalap/Classfiles.scala +++ b/src/scalap/scala/tools/scalap/Classfiles.scala @@ -26,6 +26,9 @@ object Classfiles { final val CONSTANT_METHODREF = 10 final val CONSTANT_INTFMETHODREF = 11 final val CONSTANT_NAMEANDTYPE = 12 + final val CONSTANT_METHODHANDLE = 15 + final val CONSTANT_METHODTYPE = 16 + final val CONSTANT_INVDYNAMIC = 18 final val constantTagToString = Map( CONSTANT_UTF8 -> "UTF8", @@ -39,7 +42,10 @@ object Classfiles { CONSTANT_FIELDREF -> "Field", CONSTANT_METHODREF -> "Method", CONSTANT_INTFMETHODREF -> "InterfaceMethod", - CONSTANT_NAMEANDTYPE -> "NameAndType" + CONSTANT_NAMEANDTYPE -> "NameAndType", + CONSTANT_METHODHANDLE -> "MethodHandle", + CONSTANT_METHODTYPE -> "MethodType", + CONSTANT_INVDYNAMIC -> "InvokeDynamic" ) } |