From d2875a4d948aa08010bd9706e9116f6dc956ab2c Mon Sep 17 00:00:00 2001 From: Adam Fraser Date: Mon, 9 Jan 2023 13:11:26 -0800 Subject: [PATCH 1/3] add observer before starting fiber --- core/shared/src/main/scala/zio/Runtime.scala | 44 ++++++++++++-------- 1 file changed, 26 insertions(+), 18 deletions(-) diff --git a/core/shared/src/main/scala/zio/Runtime.scala b/core/shared/src/main/scala/zio/Runtime.scala index 2381474a0388..df98d0506840 100644 --- a/core/shared/src/main/scala/zio/Runtime.scala +++ b/core/shared/src/main/scala/zio/Runtime.scala @@ -136,22 +136,7 @@ trait Runtime[+R] { self => } def fork[E, A](zio: ZIO[R, E, A])(implicit trace: Trace, unsafe: Unsafe): internal.FiberRuntime[E, A] = { - import internal.FiberRuntime - - val fiberId = FiberId.make(trace) - val fiberRefs = self.fiberRefs.updatedAs(fiberId)(FiberRef.currentEnvironment, environment) - val fiber = FiberRuntime[E, A](fiberId, fiberRefs.forkAs(fiberId), runtimeFlags) - - FiberScope.global.add(null, runtimeFlags, fiber) - - val supervisor = fiber.getSupervisor() - - if (supervisor ne Supervisor.none) { - supervisor.onStart(environment, zio, None, fiber) - - fiber.addObserver(exit => supervisor.onEnd(exit, fiber)) - } - + val fiber = makeFiber(zio) fiber.start[R](zio) fiber } @@ -161,19 +146,42 @@ trait Runtime[+R] { self => )(implicit trace: Trace, unsafe: Unsafe): CancelableFuture[A] = { val p: scala.concurrent.Promise[A] = scala.concurrent.Promise[A]() - val fiber = fork(zio) + val fiber = makeFiber(zio) fiber.addObserver(_.foldExit(cause => p.failure(cause.squashTraceWith(identity)), p.success)) + fiber.start(zio) + new CancelableFuture[A](p.future) { def cancel(): Future[Exit[Throwable, A]] = { val p: scala.concurrent.Promise[Exit[Throwable, A]] = scala.concurrent.Promise[Exit[Throwable, A]]() - val cancelFiber = fork(fiber.interruptAs(FiberId.None)) + val cancelFiber = makeFiber(ZIO.interruptAs(FiberId.None)) cancelFiber.addObserver(_.foldExit(cause => p.failure(cause.squashTraceWith(identity)), p.success)) + cancelFiber.start(ZIO.interruptAs(FiberId.None)) p.future } } } + + private def makeFiber[E, A]( + zio: ZIO[R, E, A] + )(implicit trace: Trace, unsafe: Unsafe): internal.FiberRuntime[E, A] = { + val fiberId = FiberId.make(trace) + val fiberRefs = self.fiberRefs.updatedAs(fiberId)(FiberRef.currentEnvironment, environment) + val fiber = FiberRuntime[E, A](fiberId, fiberRefs.forkAs(fiberId), runtimeFlags) + + FiberScope.global.add(null, runtimeFlags, fiber) + + val supervisor = fiber.getSupervisor() + + if (supervisor ne Supervisor.none) { + supervisor.onStart(environment, zio, None, fiber) + + fiber.addObserver(exit => supervisor.onEnd(exit, fiber)) + } + + fiber + } } } From c156dc85557bf2c7a54868366702374b79b6b1f3 Mon Sep 17 00:00:00 2001 From: Adam Fraser Date: Mon, 9 Jan 2023 20:59:07 -0800 Subject: [PATCH 2/3] cleanup --- core/shared/src/main/scala/zio/Runtime.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/shared/src/main/scala/zio/Runtime.scala b/core/shared/src/main/scala/zio/Runtime.scala index df98d0506840..3704769cd047 100644 --- a/core/shared/src/main/scala/zio/Runtime.scala +++ b/core/shared/src/main/scala/zio/Runtime.scala @@ -155,9 +155,9 @@ trait Runtime[+R] { self => new CancelableFuture[A](p.future) { def cancel(): Future[Exit[Throwable, A]] = { val p: scala.concurrent.Promise[Exit[Throwable, A]] = scala.concurrent.Promise[Exit[Throwable, A]]() - val cancelFiber = makeFiber(ZIO.interruptAs(FiberId.None)) + val cancelFiber = makeFiber(fiber.interruptAs(FiberId.None)) cancelFiber.addObserver(_.foldExit(cause => p.failure(cause.squashTraceWith(identity)), p.success)) - cancelFiber.start(ZIO.interruptAs(FiberId.None)) + cancelFiber.start(fiber.interruptAs(FiberId.None)) p.future } } From 006d96aedc8646eb3c2f02449c53b51d9e9dc30f Mon Sep 17 00:00:00 2001 From: Adam Fraser Date: Mon, 9 Jan 2023 21:09:09 -0800 Subject: [PATCH 3/3] add test --- .../src/test/scala/zio/CancelableFutureSpec.scala | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/core-tests/shared/src/test/scala/zio/CancelableFutureSpec.scala b/core-tests/shared/src/test/scala/zio/CancelableFutureSpec.scala index f48bb77a6bf0..34f4372b77b5 100644 --- a/core-tests/shared/src/test/scala/zio/CancelableFutureSpec.scala +++ b/core-tests/shared/src/test/scala/zio/CancelableFutureSpec.scala @@ -4,6 +4,8 @@ import zio.test.Assertion._ import zio.test.TestAspect._ import zio.test._ +import scala.concurrent.Future + object CancelableFutureSpec extends ZIOBaseSpec { import ZIOTag._ @@ -40,6 +42,18 @@ object CancelableFutureSpec extends ZIOBaseSpec { assertZIO(Live.live(result.timeout(1.seconds)))(isNone) } @@ zioTag(supervision, regression), + test("unsafeRunToFuture") { + for { + runtime <- ZIO.runtime[Any] + _ <- ZIO.fromFuture { implicit ec => + Future.traverse(0 to 1000) { _ => + Unsafe.unsafe { implicit unsafe => + runtime.unsafe.runToFuture(ZIO.unit) + } + } + } + } yield assertCompletes + } @@ nonFlaky, test("unsafeRunToFuture interruptibility") { for { runtime <- ZIO.runtime[Any]