From 6f0c822fc62a58a81fee14fb204990dced6e4194 Mon Sep 17 00:00:00 2001 From: Gavin Bisesi Date: Fri, 27 Nov 2020 20:12:30 -0500 Subject: [PATCH] Allow `IOApp` to access the default ExecutionContext Currently it's not possible for users of `IOApp` to use the default ExecutionContext that backs the ContextShift. They need to either use `IOApp.WithContext`, or use two unrelated pools, or override the default `ContextShift`. This should remove some needless hoop-jumping, I think Close #748 --- .../cats/effect/internals/IOAppPlatform.scala | 6 ++++-- .../internals/IOAppCompanionPlatform.scala | 2 +- .../cats/effect/internals/IOAppPlatform.scala | 5 +++++ .../src/main/scala/cats/effect/IOApp.scala | 19 +++++++++++++++++++ 4 files changed, 29 insertions(+), 3 deletions(-) diff --git a/core/js/src/main/scala/cats/effect/internals/IOAppPlatform.scala b/core/js/src/main/scala/cats/effect/internals/IOAppPlatform.scala index 9cf375d25b..4407f4da88 100644 --- a/core/js/src/main/scala/cats/effect/internals/IOAppPlatform.scala +++ b/core/js/src/main/scala/cats/effect/internals/IOAppPlatform.scala @@ -21,6 +21,7 @@ package internals import cats.syntax.all._ import scala.concurrent.duration._ import scala.scalajs.js +import scala.concurrent.ExecutionContext private[effect] object IOAppPlatform { def main(args: Array[String], cs: Eval[ContextShift[IO]], timer: Eval[Timer[IO]])( @@ -41,8 +42,8 @@ private[effect] object IOAppPlatform { /** * Sets the exit code with `process.exitCode = code` for runtimes * that support it. This allows a graceful shutdown with a specific - * exit code. - * + * exit code. + * * If the call is not supported and the exit code is not Success, * then it is logged. * @@ -82,6 +83,7 @@ private[effect] object IOAppPlatform { val defaultTimer: Timer[IO] = IOTimer.global val defaultContextShift: ContextShift[IO] = IOContextShift.global + val defaultExecutionContext: ExecutionContext = ExecutionContext.Implicits.global private def installHandler(fiber: Fiber[IO, Int]): IO[Unit] = { def handler(code: Int) = diff --git a/core/jvm/src/main/scala/cats/effect/internals/IOAppCompanionPlatform.scala b/core/jvm/src/main/scala/cats/effect/internals/IOAppCompanionPlatform.scala index 83771b9c6f..c052c64ca1 100644 --- a/core/jvm/src/main/scala/cats/effect/internals/IOAppCompanionPlatform.scala +++ b/core/jvm/src/main/scala/cats/effect/internals/IOAppCompanionPlatform.scala @@ -83,7 +83,7 @@ private[effect] trait IOAppCompanionPlatform { * [[executionContextResource]]. Outside `run`, this context will * reject all tasks. */ - final protected def executionContext: ExecutionContext = + final override protected def executionContext: ExecutionContext = currentContext.get().executionContext /** diff --git a/core/jvm/src/main/scala/cats/effect/internals/IOAppPlatform.scala b/core/jvm/src/main/scala/cats/effect/internals/IOAppPlatform.scala index 4f072c019e..3fc877276d 100644 --- a/core/jvm/src/main/scala/cats/effect/internals/IOAppPlatform.scala +++ b/core/jvm/src/main/scala/cats/effect/internals/IOAppPlatform.scala @@ -18,6 +18,8 @@ package cats package effect package internals +import scala.concurrent.ExecutionContext + private[effect] object IOAppPlatform { def main(args: Array[String], contextShift: Eval[ContextShift[IO]], timer: Eval[Timer[IO]])( run: List[String] => IO[ExitCode] @@ -58,6 +60,9 @@ private[effect] object IOAppPlatform { def defaultContextShift: ContextShift[IO] = IOContextShift(PoolUtils.ioAppGlobal) + def defaultExecutionContext: ExecutionContext = + PoolUtils.ioAppGlobal + private def installHook(fiber: Fiber[IO, Int]): IO[Unit] = IO { sys.addShutdownHook { diff --git a/core/shared/src/main/scala/cats/effect/IOApp.scala b/core/shared/src/main/scala/cats/effect/IOApp.scala index add9a360ae..7b14ee9d33 100644 --- a/core/shared/src/main/scala/cats/effect/IOApp.scala +++ b/core/shared/src/main/scala/cats/effect/IOApp.scala @@ -18,6 +18,7 @@ package cats package effect import cats.effect.internals.{IOAppCompanionPlatform, IOAppPlatform} +import scala.concurrent.ExecutionContext /** * `App` type that runs a [[cats.effect.IO]]. Shutdown occurs after @@ -100,6 +101,24 @@ trait IOApp { */ implicit protected def timer: Timer[IO] = IOAppPlatform.defaultTimer + + /** + * Provides a default `ExecutionContext` for the app. + * + * The default on top of the JVM is lazily constructed as a fixed + * thread pool based on number available of available CPUs (see + * `PoolUtils`). + * + * On top of JavaScript, this will use the standard + * [[https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout setTimeout]]. + * + * @note This is the same ExecutionContext that backs the default implicit `ContextShift` + * + * @note To use a different `ExecutionContext`, consider extending `IOApp.WithContext`, + * which will do it more comprehensively. + */ + protected def executionContext: ExecutionContext = + IOAppPlatform.defaultExecutionContext } object IOApp extends IOAppCompanionPlatform