diff --git a/core/js/src/main/scala/zio/internal/PlatformSpecific.scala b/core/js/src/main/scala/zio/internal/PlatformSpecific.scala index 04d28e061b1d..470697312172 100644 --- a/core/js/src/main/scala/zio/internal/PlatformSpecific.scala +++ b/core/js/src/main/scala/zio/internal/PlatformSpecific.scala @@ -74,6 +74,8 @@ private[internal] trait PlatformSpecific { new Platform { val executor = executor0 + val yieldOnStart = false + def fatal(t: Throwable): Boolean = false def reportFatal(t: Throwable): Nothing = { diff --git a/core/jvm/src/main/scala/zio/internal/PlatformSpecific.scala b/core/jvm/src/main/scala/zio/internal/PlatformSpecific.scala index a4787e875480..8d4857031812 100644 --- a/core/jvm/src/main/scala/zio/internal/PlatformSpecific.scala +++ b/core/jvm/src/main/scala/zio/internal/PlatformSpecific.scala @@ -80,6 +80,8 @@ private[internal] trait PlatformSpecific { new Platform { val executor = executor0 + val yieldOnStart = true + val tracing = Tracing(Tracer.globallyCached(new AkkaLineNumbersTracer), TracingConfig.enabled) def fatal(t: Throwable): Boolean = diff --git a/core/native/src/main/scala/zio/internal/PlatformSpecific.scala b/core/native/src/main/scala/zio/internal/PlatformSpecific.scala index 098b404d4bb9..5ed8e5e0641e 100644 --- a/core/native/src/main/scala/zio/internal/PlatformSpecific.scala +++ b/core/native/src/main/scala/zio/internal/PlatformSpecific.scala @@ -74,6 +74,8 @@ private[internal] trait PlatformSpecific { new Platform { val executor = executor0 + val yieldOnStart = false + def fatal(t: Throwable): Boolean = false def reportFatal(t: Throwable): Nothing = { diff --git a/core/shared/src/main/scala/zio/Runtime.scala b/core/shared/src/main/scala/zio/Runtime.scala index 4015aafbea92..7bb7838acb04 100644 --- a/core/shared/src/main/scala/zio/Runtime.scala +++ b/core/shared/src/main/scala/zio/Runtime.scala @@ -102,7 +102,7 @@ trait Runtime[+R] { * This method is effectful and should only be invoked at the edges of your program. */ final def unsafeRunAsyncCancelable[E, A](zio: => ZIO[R, E, A])(k: Exit[E, A] => Any): Fiber.Id => Exit[E, A] = { - lazy val curZio = if (Platform.isJVM) ZIO.yieldNow *> zio else zio + lazy val curZio = if (platform.yieldOnStart) ZIO.yieldNow *> zio else zio val canceler = unsafeRunWith(curZio)(k) fiberId => { val result = internal.OneShot.make[Exit[E, A]] @@ -168,6 +168,11 @@ trait Runtime[+R] { */ def withTracing(t: Tracing): Runtime[R] = mapPlatform(_.withTracing(t)) + /** + * Constructs a new `Runtime` with the specified yield strategy. + */ + def withYieldOnStart(cond: Boolean): Runtime[R] = mapPlatform(_.withYieldOnStart(cond)) + /** * Constructs a new `Runtime` with the specified tracing configuration. */ diff --git a/core/shared/src/main/scala/zio/internal/Platform.scala b/core/shared/src/main/scala/zio/internal/Platform.scala index 6328b2e87849..4a481204642f 100644 --- a/core/shared/src/main/scala/zio/internal/Platform.scala +++ b/core/shared/src/main/scala/zio/internal/Platform.scala @@ -30,6 +30,11 @@ abstract class Platform { self => */ def executor: Executor + /** + * Specifies if ZIO should yield immediately or not. + */ + def yieldOnStart: Boolean + def withExecutor(e: Executor): Platform = new Platform.Proxy(self) { override def executor: Executor = e @@ -50,6 +55,14 @@ abstract class Platform { self => override val tracing: Tracing = self.tracing.copy(tracingConfig = config) } + /** + * Determines if the `Runtime` should yield right at the beginning of the evaluation. + */ + def withYieldOnStart(cond: Boolean): Platform = + new Platform.Proxy(self) { + override val yieldOnStart: Boolean = cond + } + /** * Determines if a throwable is fatal or not. It is important to identify * these as it is not recommended to catch, and try to recover from, any @@ -97,5 +110,6 @@ object Platform extends PlatformSpecific { def reportFatal(t: Throwable): Nothing = self.reportFatal(t) def reportFailure(cause: Cause[Any]): Unit = self.reportFailure(cause) def supervisor: Supervisor[Any] = self.supervisor + def yieldOnStart: Boolean = self.yieldOnStart } }