summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/library/scala/collection/JavaConverters.scala12
-rw-r--r--src/library/scala/collection/mutable/ListBuffer.scala4
-rw-r--r--src/library/scala/concurrent/ExecutionContext.scala42
-rw-r--r--src/library/scala/concurrent/package.scala43
-rw-r--r--src/scalap/scala/tools/scalap/Classfile.scala6
-rw-r--r--src/scalap/scala/tools/scalap/Classfiles.scala8
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"
)
}