All Downloads are FREE. Search and download functionalities are using the official Maven repository.

colibri.effect.RunEffect.scala Maven / Gradle / Ivy

The newest version!
package colibri.effect

import cats.effect.std.Dispatcher
import cats.effect.{Async, IO, Resource, SyncIO, unsafe}
import colibri.Cancelable

trait RunEffect[-F[_]] {
  def unsafeRunAsyncCancelable[T](effect: F[T])(cb: Either[Throwable, T] => Unit): Cancelable
  def unsafeRunSyncOrAsyncCancelable[T](effect: F[T])(cb: Either[Throwable, T] => Unit): Cancelable
}

trait RunEffectLowPrio {
  implicit val IORunEffect: RunEffect[IO] = new RunEffectIOWithRuntime(unsafe.IORuntime.global)
}
object RunEffect extends RunEffectLowPrio {
  @inline def apply[F[_]](implicit run: RunEffect[F]): RunEffect[F] = run

  def forAsync[F[_]: Async]: Resource[F, RunEffect[F]] = Dispatcher.parallel[F].map(forDispatcher(_))

  def forDispatcher[F[_]: Async](dispatcher: Dispatcher[F]): RunEffect[F] = new RunEffectAsyncWithDispatcher(dispatcher)

  @inline implicit def IORunEffectRuntime(implicit ioRuntime: unsafe.IORuntime): RunEffect[IO] = new RunEffectIOWithRuntime(ioRuntime)

  @inline implicit def RunSyncEffectRunEffect[F[_]: RunSyncEffect]: RunEffect[F] = RunSyncEffect[F]
}

private final class RunEffectAsyncWithDispatcher[F[_]: Async](dispatcher: Dispatcher[F]) extends RunEffect[F] {
  override def unsafeRunAsyncCancelable[T](effect: F[T])(cb: Either[Throwable, T] => Unit): Cancelable = {
    val (future, cancelRun) = dispatcher.unsafeToFutureCancelable(effect)
    RunEffectExecution.handleFutureCancelable(future, cancelRun)(cb)
  }

  override def unsafeRunSyncOrAsyncCancelable[T](effect: F[T])(cb: Either[Throwable, T] => Unit): Cancelable = {
    val syncStep = Async[F].syncStep[SyncIO, T](effect, Int.MaxValue)
    RunEffectExecution.handleSyncStepCancelable[F, T](syncStep, x => unsafeRunAsyncCancelable(x)(cb))(cb)
  }

}

private final class RunEffectIOWithRuntime(ioRuntime: unsafe.IORuntime) extends RunEffect[IO] {
  override def unsafeRunAsyncCancelable[T](effect: IO[T])(cb: Either[Throwable, T] => Unit): Cancelable = {
    val (future, cancelRun) = effect.unsafeToFutureCancelable()(ioRuntime)
    RunEffectExecution.handleFutureCancelable(future, cancelRun)(cb)
  }

  override def unsafeRunSyncOrAsyncCancelable[T](effect: IO[T])(cb: Either[Throwable, T] => Unit): Cancelable = {
    val syncStep = effect.syncStep(Int.MaxValue)
    RunEffectExecution.handleSyncStepCancelable[IO, T](syncStep, x => unsafeRunAsyncCancelable(x)(cb))(cb)
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy