From 832b3eff7cbc1f2ee9c80cad6b032b6aeea286b8 Mon Sep 17 00:00:00 2001 From: Viktor Klang Date: Thu, 29 Oct 2020 22:11:27 +0100 Subject: [PATCH] Introduces ExecutionContext.opportunistic as a private[scala] instance as an escape-hatch for getting the original 2.13.0 batching global EC --- build.sbt | 3 +++ .../scala/concurrent/ExecutionContext.scala | 19 +++++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/build.sbt b/build.sbt index 3d17449e1032..55218f7db963 100644 --- a/build.sbt +++ b/build.sbt @@ -456,6 +456,9 @@ val mimaFilterSettings = Seq { ProblemFilters.exclude[MissingClassProblem]("scala.collection.mutable.MutationTracker"), ProblemFilters.exclude[MissingClassProblem]("scala.collection.mutable.MutationTracker$"), ProblemFilters.exclude[MissingClassProblem]("scala.collection.mutable.MutationTracker$CheckedIterator"), + + // Escape hatch for getting Scala 2.13.0 behavior of the global ExecutionContext + ProblemFilters.exclude[MissingClassProblem]("scala.concurrent.ExecutionContext$opportunistic$"), ), } diff --git a/src/library/scala/concurrent/ExecutionContext.scala b/src/library/scala/concurrent/ExecutionContext.scala index 28af1770fa09..78b06f993126 100644 --- a/src/library/scala/concurrent/ExecutionContext.scala +++ b/src/library/scala/concurrent/ExecutionContext.scala @@ -166,6 +166,25 @@ object ExecutionContext { override final def reportFailure(t: Throwable): Unit = defaultReporter(t) } + /** + * This `ExecutionContext` is ideally suited to execute short-lived tasks on the `global` `ExecutionContext` as it + * attempts to locally batch the execution of nested tasks. + * + * WARNING: long-running and/or blocking tasks should be demarcated within `scala.concurrent.blocking`-blocks, + * to ensure that any pending tasks in the current batch can be executed by another thread on `global`. + */ + private[scala] object opportunistic extends ExecutionContextExecutor with BatchingExecutor { + final override def submitForExecution(runnable: Runnable): Unit = global.execute(runnable) + + final override def execute(runnable: Runnable): Unit = + if ((!runnable.isInstanceOf[impl.Promise.Transformation[_,_]] || runnable.asInstanceOf[impl.Promise.Transformation[_,_]].benefitsFromBatching) && runnable.isInstanceOf[Batchable]) + submitAsyncBatched(runnable) + else + submitForExecution(runnable) + + override final def reportFailure(t: Throwable): Unit = global.reportFailure(t) + } + object Implicits { /** * The implicit global `ExecutionContext`. Import `global` when you want to provide the global