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

turbolift.internals.engine.Engine.scala Maven / Gradle / Ivy

The newest version!
package turbolift.internals.engine
import java.util.concurrent.TimeUnit
import scala.annotation.{tailrec, switch}
import turbolift.{!!, Computation, Signature, ComputationCases => CC}
import turbolift.io.{Fiber, Zipper, Warp, Snap, Outcome, Cause, Exceptions}
import turbolift.io.{OnceVar, CountDownLatch, CyclicBarrier, Mutex, Semaphore, Channel}
import turbolift.interpreter.{Interpreter, Continuation}
import turbolift.internals.executor.Executor
import turbolift.internals.engine.stacked.{Stack, Store, Local, Prompt, FrameKind, OpPush, OpSplit, OpCascaded}
import turbolift.internals.engine.concurrent.{Bits, Blocker, Waitee, FiberImpl, WarpImpl}
import turbolift.internals.engine.concurrent.util.{OnceVarImpl, CountDownLatchImpl, CyclicBarrierImpl, MutexImpl, SemaphoreImpl, ChannelImpl}
import Tag.{Retire => ThreadDisowned}
import Local.Syntax._
import Cause.{Cancelled => CancelPayload}
import Misc._


private sealed abstract class Engine0 extends Runnable:
  protected var currentFiber: FiberImpl = null.asInstanceOf[FiberImpl]
  protected var currentEnv: Env = null.asInstanceOf[Env]
  protected var currentTickLow: Int = 0
  protected var currentTickHigh: Int = 0


/*private[turbolift]*/ abstract class Engine extends Engine0:
  protected var savedPayload: Any = null
  protected var savedStep: Step = null.asInstanceOf[Step]
  protected var savedStack: Stack = null.asInstanceOf[Stack]
  protected var savedStore: Store = null.asInstanceOf[Store]
  protected val pad1 = 0L
  protected val pad2 = 0L


  def this(fiber: FiberImpl) = { this(); become(fiber) }


  final def runCurrent(): Halt =
    currentTickLow = currentEnv.tickLow
    currentTickHigh = currentEnv.tickHigh
    currentFiber.theWaiteeOrBlocker = null //// for those resumed by `finallyResumeAllWaiters`
    if cancellationCheck() then
      currentFiber.suspendAsCancelled()
    outerLoop()

  
  //-------------------------------------------------------------------
  // Outer Loop
  //-------------------------------------------------------------------


  @tailrec private final def outerLoop(): Halt =
    val result =
      val tag =
        val tag1          = currentFiber.suspendedTag
        this.savedPayload = currentFiber.suspendedPayload
        this.savedStep    = currentFiber.suspendedStep.nn
        this.savedStack   = currentFiber.suspendedStack.nn
        this.savedStore   = currentFiber.suspendedStore.nn
        currentFiber.clearSuspension()
        dispatchNotify(tag1)

      try
        middleLoop(tag)
      catch e =>
        // e.printStackTrace()
        val e2 = if e.isInstanceOf[Exceptions.Panic] then e else new Exceptions.Unhandled(e)
        val c = Cause(e2)
        endOfLoop(Bits.Completion_Failure, c, null)

    result match
      case Tag.Become => outerLoop()
      case Tag.Yield => Halt.Yield
      case Tag.Retire => Halt.Retire


  //-------------------------------------------------------------------
  // Middle Loop
  //-------------------------------------------------------------------


  @tailrec private final def middleLoop(tag: Tag): Tag =
    val tag2 =
      (tag: @switch) match
        case (
          Tag.FlatMap | Tag.PureMap | Tag.MoreFlat | Tag.MorePure |
          Tag.Perform | Tag.Pure | Tag.Impure |
          Tag.LocalGet | Tag.LocalPut | Tag.LocalUpdate | Tag.Sync
        ) =>
          val payload = savedPayload
          val step    = savedStep
          val stack   = savedStack
          val store   = savedStore
          clearSaved()
          innerLoop(tag, payload, step, stack, store)

        case Tag.Intrinsic =>
          val instr = savedPayload.asInstanceOf[CC.Intrinsic[Any, Any]]
          instr(this)

        case Tag.Unwind => doUnwind()

        case Tag.Become | Tag.Yield | Tag.Retire => tag

    if tag2 < Tag.Become then
      middleLoop(tag2)
    else
      if tag2 < Tag.TickReset then
        tag2
      else
        val tag3 = tag2 - Tag.TickReset
        assert(tag3 < Tag.Become)
        if currentTickHigh > 0 then
          currentTickHigh -= 1
          currentTickLow = currentEnv.tickLow
          val tag4 =
            if cancellationCheck() then
              this.savedPayload = CancelPayload
              this.savedStep = Step.Cancel
              Tag.Unwind
            else
              tag3
          middleLoop(tag4)
        else
          currentFiber.suspend(tag3, savedPayload, savedStep, savedStack, savedStore)
          clearSaved()
          Tag.Yield


  //-------------------------------------------------------------------
  // Inner Loop
  //-------------------------------------------------------------------


  @tailrec private final def innerLoop(tag: Tag, payload: Any, step: Step, stack: Stack, store: Store): Tag =
    inline def innerLoopStep(payload: Any, step: Step, store: Store): Tag =
      innerLoop(step.tag, payload, step, stack, store)

    inline def innerLoopComp(comp: Computation[?, ?], step: Step, store: Store): Tag =
      innerLoop(comp.tag, comp, step, stack, store)

    inline def loopTag(tag: Tag, payload: Any, step: Step, store: Store): Tag =
      val tag2 = if tag == Tag.FlatMap then payload.asInstanceOf[AnyComp].tag else step.tag
      innerLoop(tag2, payload, step, stack, store)

    if currentTickLow > 0 then
      currentTickLow -= 1
      (tag: @switch) match
        case Tag.FlatMap | Tag.PureMap =>
          val instr1 = payload.asInstanceOf[CC.Map[Any, Any, Any, Any]]
          val comp1 = instr1.comp
          (comp1.tag: @switch) match
            case Tag.Pure =>
              val instr2 = comp1.asInstanceOf[CC.Pure[Any]]
              val payload2 = instr1(instr2.value)
              loopTag(tag, payload2, step, store)

            case Tag.Impure =>
              val instr2 = comp1.asInstanceOf[CC.Impure[Any]]
              val payload2 = instr1(instr2())
              loopTag(tag, payload2, step, store)

            case Tag.Perform =>
              val instr2 = comp1.asInstanceOf[CC.Perform[Any, Any, Signature]]
              val entry = stack.findEntryBySignature(instr2.sig)
              val comp2 = instr2(entry.prompt)
              (comp2.tag: @switch) match
                case Tag.Pure =>
                  val instr3 = comp2.asInstanceOf[CC.Pure[Any]]
                  val payload2 = instr1(instr3.value)
                  loopTag(tag, payload2, step, store)

                case Tag.Impure =>
                  val instr3 = comp2.asInstanceOf[CC.Impure[Any]]
                  val payload2 = instr1(instr3())
                  loopTag(tag, payload2, step, store)

                case Tag.LocalGet =>
                  val local = store.deepGet(entry.storeIndex, entry.segmentDepth)
                  val payload2 = instr1(local)
                  loopTag(tag, payload2, step, store)

                case Tag.LocalPut =>
                  val instr3 = comp2.asInstanceOf[CC.LocalPut[Local]]
                  val store2 = store.deepPut(entry.storeIndex, entry.segmentDepth, instr3.local)
                  val payload2 = instr1(())
                  loopTag(tag, payload2, step, store2)

                case Tag.LocalUpdate =>
                  val instr3 = comp2.asInstanceOf[CC.LocalUpdate[Any, Local]]
                  val store2 = store.deepClone(entry.segmentDepth)
                  val value = store2.deepUpdateInPlace(entry.storeIndex, entry.segmentDepth, instr3)
                  val payload2 = instr1(value)
                  loopTag(tag, payload2, step, store2)

                case _ =>
                  val tag2 = tag + Tag.MoreFlat - Tag.FlatMap
                  val step2 = Step.More(tag2, instr1, step)
                  innerLoopComp(comp2, step2, store)

            case _ =>
              val tag2 = tag + Tag.MoreFlat - Tag.FlatMap
              val step2 = Step.More(tag2, instr1, step)
              innerLoopComp(comp1, step2, store)

        case Tag.MoreFlat =>
          val instr = step.asInstanceOf[Step.More]
          val step2 = instr.next
          val comp2 = instr.fun(payload).asInstanceOf[AnyComp]
          innerLoopComp(comp2, step2, store)

        case Tag.MorePure =>
          val instr = step.asInstanceOf[Step.More]
          val step2 = instr.next
          val payload2 = instr.fun(payload)
          innerLoopStep(payload2, step2, store)

        case Tag.Perform =>
          val instr = payload.asInstanceOf[CC.Perform[Any, Any, Signature]]
          val entry = stack.findEntryBySignature(instr.sig)
          val comp2 = instr(entry.prompt)
          (comp2.tag: @switch) match
            case Tag.LocalGet =>
              val local = store.deepGet(entry.storeIndex, entry.segmentDepth)
              innerLoopStep(local, step, store)

            case Tag.LocalPut =>
              val instr2 = comp2.asInstanceOf[CC.LocalPut[Local]]
              val store2 = store.deepPut(entry.storeIndex, entry.segmentDepth, instr2.local)
              innerLoopStep((), step, store2)

            case Tag.LocalUpdate =>
              val instr2 = comp2.asInstanceOf[CC.LocalUpdate[Any, Local]]
              val store2 = store.deepClone(entry.segmentDepth)
              val value = store2.deepUpdateInPlace(entry.storeIndex, entry.segmentDepth, instr2)
              innerLoopStep(value, step, store2)

            case _ => innerLoopComp(comp2, step, store)

        case Tag.Pure =>
          val instr = payload.asInstanceOf[CC.Pure[Any]]
          val payload2 = instr.value
          innerLoopStep(payload2, step, store)

        case Tag.Impure =>
          val instr = payload.asInstanceOf[CC.Impure[Any]]
          val payload2 = instr()
          innerLoopStep(payload2, step, store)

        case Tag.LocalGet =>
          val instr = payload.asInstanceOf[CC.LocalGet]
          val entry = stack.findEntryByPrompt(instr.prompt)
          val local = store.deepGet(entry.storeIndex, entry.segmentDepth)
          innerLoopStep(local, step, store)

        case Tag.LocalPut =>
          val instr = payload.asInstanceOf[CC.LocalPut[Local]]
          val entry = stack.findEntryByPrompt(instr.prompt)
          val store2 = store.deepPut(entry.storeIndex, entry.segmentDepth, instr.local)
          innerLoopStep((), step, store2)

        case Tag.LocalUpdate =>
          val instr = payload.asInstanceOf[CC.LocalUpdate[Any, Local]]
          val entry = stack.findEntryByPrompt(instr.prompt)
          val store2 = store.deepClone(entry.segmentDepth)
          val value = store2.deepUpdateInPlace(entry.storeIndex, entry.segmentDepth, instr)
          innerLoopStep(value, step, store2)

        case Tag.Sync =>
          val instr = payload.asInstanceOf[CC.Sync[Any, Any]]
          var result: Any = null
          var throwable: Throwable | Null = null
          try
            result = instr()
          catch
            case e => throwable = e
          if throwable == null then
            val payload2 = if instr.isAttempt then Right(result) else result
            innerLoopStep(payload2, step, store)
          else
            if instr.isAttempt then
              innerLoopStep(Left(throwable), step, store)
            else
              innerLoopStep(Cause(throwable.nn), Step.Throw, store)

        case Tag.Intrinsic | Tag.Unwind =>
          this.savedPayload = payload
          this.savedStep    = step
          this.savedStack   = stack
          this.savedStore   = store
          tag
    else
      this.savedPayload = payload
      this.savedStep    = step
      this.savedStack   = stack
      this.savedStore   = store
      Tag.TickReset + tag


  //-------------------------------------------------------------------
  // Loop Aux
  //-------------------------------------------------------------------


  private final def endOfLoop(completion: Int, payload: Any, stack: Stack | Null): Tag =
    currentFiber.doFinalize(completion, payload, stack) match
      case null => Tag.Retire
      case fiber2 => become(fiber2.nn); Tag.Become


  private final def dispatchNotify(tag: Tag): Tag =
    val tag2 = savedStep.tag
    (tag: @switch) match
      case Tag.NotifyOnceVar =>
        val ovar = savedPayload.asInstanceOf[OnceVarImpl]
        this.savedPayload = ovar.theContent
        tag2

      case Tag.NotifyZipper =>
        val fiber = savedPayload.asInstanceOf[FiberImpl]
        this.savedPayload = fiber.getOrMakeZipper
        tag2

      case Tag.NotifyUnit =>
        this.savedPayload = ()
        tag2

      case _ => tag


  private final def doUnwind(): Tag =
    val payload = savedPayload
    val step    = savedStep
    val stack   = savedStack
    val store   = savedStore
    //-------------------
    val instr = step.asInstanceOf[Step.Unwind]
    if stack.canPop then
      if instr.isBridge then
        val (stack2, store2, step2) = OpPush.drop(stack, store)
        refreshEnv(stack2, store2)
        loopStep(payload, step2, stack2, store2)
      else
        val (stack2, store2, step2, prompt, frame, local) = OpPush.pop(stack, store)
        val fallthrough = if instr.isPop then step2 else step
        if prompt.isIo then
          (frame.kind.unwrap: @switch) match
            case FrameKind.PLAIN =>
              loopStepRefreshEnv(payload, fallthrough, stack2, store2)

            case FrameKind.GUARD =>
              val payload2 = instr.kind match
                case Step.UnwindKind.Pop    => Snap.Success(payload)
                case Step.UnwindKind.Abort  => Snap.Aborted(payload, instr.prompt.nn)
                case Step.UnwindKind.Cancel => Snap.Cancelled
                case Step.UnwindKind.Throw  => Snap.Failure(payload.asInstanceOf[Cause])
                case Step.UnwindKind.Bridge => impossible
              loopStepRefreshEnv(payload2, step2, stack2, store2)

            case FrameKind.WARP =>
              currentFiber.suspendStep(payload, fallthrough, stack2, store2)
              val warp = currentEnv.currentWarp.nn
              val tried = warp.exitMode match
                case Warp.ExitMode.Cancel => warp.tryGetCancelledBy(currentFiber, currentEnv.isCancellable)
                case Warp.ExitMode.Await => warp.tryGetAwaitedBy(currentFiber, currentEnv.isCancellable)
                case _ => impossible //// this is a scoped warp, so it must have ExitMode
              tried match
                case Bits.WaiterSubscribed => ThreadDisowned
                case Bits.WaiterAlreadyCancelled => impossible //// Latch is set
                case Bits.WaiteeAlreadyCompleted =>
                  currentFiber.clearSuspension()
                  loopStepRefreshEnv(payload, fallthrough, stack2, store2)

            case FrameKind.EXEC =>
              currentFiber.suspendStep(payload, fallthrough, stack2, store2)
              currentFiber.resume()
              ThreadDisowned

            case FrameKind.SUPPRESS =>
              refreshEnv(stack2, store2)
              if cancellationCheck() then
                loopCancel(stack2, store2)
              else
                loopStep(payload, fallthrough, stack2, store2)
          end match
        else //// isIo
          if instr.isPop then
            val comp2 = prompt.onReturn(payload, local)
            loopComp(comp2, step2, stack2, store2)
          else
            val step3 = if prompt == instr.prompt then step2 else step
            loopStep(payload, step3, stack2, store2)
      end if //// isBridge
    else
      val completion = instr.kind match
        case Step.UnwindKind.Pop    => Bits.Completion_Success
        case Step.UnwindKind.Cancel => Bits.Completion_Cancelled
        case Step.UnwindKind.Throw  => Bits.Completion_Failure
        case _                      => impossible
      endOfLoop(completion, payload, stack)


  //-------------------------------------------------------------------
  // Intrinsics Aux
  //-------------------------------------------------------------------


  private final def loopStep(value: Any, step: Step, stack: Stack, store: Store): Tag =
    savedPayload = value
    savedStep = step
    savedStack = stack
    savedStore = store
    step.tag

  private final def loopComp(comp: !![?, ?], step: Step, stack: Stack, store: Store): Tag =
    savedPayload = comp
    savedStep = step
    savedStack = stack
    savedStore = store
    comp.tag

  private final def loopStepRefreshEnv(value: Any, step: Step, stack: Stack, store: Store): Tag =
    refreshEnv(stack, store)
    loopStep(value, step, stack, store)

  private final def loopCompRefreshEnv(comp: !![?, ?], step: Step, stack: Stack, store: Store): Tag =
    refreshEnv(stack, store)
    loopComp(comp, step, stack, store)

  private final def loopCancel(stack: Stack, store: Store): Tag =
    loopStep(CancelPayload, Step.Cancel, stack, store)


  //-------------------------------------------------------------------
  // Intrinsics
  //-------------------------------------------------------------------


  final def intrinsicDelimitPut[S](prompt: Prompt, body: AnyComp, local: S): Tag =
    val step = savedStep
    val stack = savedStack
    val store = savedStore
    //-------------------
    val location = stack.locatePrompt(prompt)
    val (stack2, store2) = OpPush.pushNested(stack, store, step, prompt, location, local.asLocal, FrameKind.plain)
    loopComp(body, Step.Pop, stack2, store2)


  final def intrinsicDelimitMod[S](prompt: Prompt, body: AnyComp, fun: S => S): Tag =
    val step = savedStep
    val stack = savedStack
    val store = savedStore
    //-------------------
    val location = stack.locatePrompt(prompt)
    val local2 = fun.asInstanceOf[Local => Local](store.deepGet(location))
    val (stack2, store2) = OpPush.pushNested(stack, store, step, prompt, location, local2, FrameKind.plain)
    loopComp(body, Step.Pop, stack2, store2)


  final def intrinsicAbort(prompt: Prompt, value: Any): Tag =
    val step = savedStep
    val stack = savedStack
    val store = savedStore
    //-------------------
    loopStep(value, Step.abort(prompt), stack, store)


  final def intrinsicResume[A, B, S, U](cont0: Continuation[A, B, S, U], value: A): Tag =
    val step = savedStep
    val stack = savedStack
    val store = savedStore
    //-------------------
    val cont = cont0.asImpl
    val (stack2, store2) = OpSplit.merge(
      stackHi = cont.stack,
      storeHi = cont.store,
      stepMid = step,
      stackLo = stack,
      storeLo = store,
    )
    loopStepRefreshEnv(value, cont.step, stack2, store2)


  final def intrinsicResumePut[A, B, S, U](cont0: Continuation[A, B, S, U], value: A, local: S): Tag =
    val step = savedStep
    val stack = savedStack
    val store = savedStore
    //-------------------
    val cont = cont0.asImpl
    val (stack2, store2) = OpSplit.merge(
      stackHi = cont.stack,
      storeHi = cont.store.deepPutIfNotVoid(cont.location, local.asLocal),
      stepMid = step,
      stackLo = stack,
      storeLo = store,
    )
    loopStepRefreshEnv(value, cont.step, stack2, store2)


  final def intrinsicCapture[A, B, S, U](prompt: Prompt, fun: Continuation[A, B, S, U] => B !! U): Tag =
    val step = savedStep
    val stack = savedStack
    val store = savedStore
    //-------------------
    val location = stack.locatePrompt(prompt)
    val (stackHi, storeHi, stepMid, stackLo, storeLo) = OpSplit.split(stack, store, location)
    //@#@THOV only the shallow paty of location2 is used
    val location2 = stackHi.locatePrompt(prompt)
    val cont = new ContImpl(stackHi, storeHi, step, location2)
    val comp2 = fun(cont.cast[A, B, S, U])
    loopCompRefreshEnv(comp2, stepMid, stackLo, storeLo)


  final def intrinsicCaptureGet[A, B, S, U](prompt: Prompt, fun: (Continuation[A, B, S, U], S) => B !! U): Tag =
    val step = savedStep
    val stack = savedStack
    val store = savedStore
    //-------------------
    val location = stack.locatePrompt(prompt)
    val (stackHi, storeHi, stepMid, stackLo, storeLo) = OpSplit.split(stack, store, location)
    //@#@THOV only the shallow paty of location2 is used
    val location2 = stackHi.locatePrompt(prompt)
    val cont = new ContImpl(stackHi, storeHi, step, location2)
    val comp2 =
      val local = storeHi.deepGet(location2)
      fun(cont.cast[A, B, S, U], local.asInstanceOf[S])
    loopCompRefreshEnv(comp2, stepMid, stackLo, storeLo)


  final def intrinsicZipPar[A, B, C, U](lhs: A !! U, rhs: B !! U, fun: (A, B) => C): Tag =
    val step = savedStep
    val stack = savedStack
    val store = savedStore
    //-------------------
    //@#@TODO Too conservative? Should check for `features.isParallel` at `mark`, instead of at stack top
    if stack.accumFeatures.isParallel && currentEnv.isParallelismRequested then
      val fiberLeft = currentFiber.createChild(Bits.ZipPar_Left)
      val fiberRight = currentFiber.createChild(Bits.ZipPar_Right)
      if currentFiber.tryStartRace(fiberLeft, fiberRight, currentEnv.isCancellable) then
        val (storeTmp, storeLeft) = OpCascaded.fork(stack, store)
        val (storeDown, storeRight) = OpCascaded.fork(stack, storeTmp)
        currentFiber.suspendForRace(fun, step, stack, storeDown)
        val stack2 = stack.makeFork
        fiberRight.suspendComp(rhs, Step.Pop, stack2, storeRight)
        fiberRight.resume()
        becomeWithSameEnv(fiberLeft)
        loopComp(lhs, Step.Pop, stack2, storeLeft)
      else
        //// Must have been cancelled meanwhile
        loopCancel(stack, store)
    else
      //// Fallback to sequential
      val comp2 = lhs.zipWith(rhs)(fun)
      loopComp(comp2, step, stack, store)


  final def intrinsicOrPar[A, U](lhs: A !! U, rhs: A !! U): Tag =
    val step = savedStep
    val stack = savedStack
    val store = savedStore
    //-------------------
    if stack.accumFeatures.isParallel && currentEnv.isParallelismRequested then
      val fiberLeft = currentFiber.createChild(Bits.OrPar_Left)
      val fiberRight = currentFiber.createChild(Bits.OrPar_Right)
      if currentFiber.tryStartRace(fiberLeft, fiberRight, currentEnv.isCancellable) then
        val (storeTmp, storeLeft) = OpCascaded.fork(stack, store)
        val (storeDown, storeRight) = OpCascaded.fork(stack, storeTmp)
        currentFiber.suspendForRace(null, step, stack, storeDown)
        val stack2 = stack.makeFork
        fiberRight.suspendComp(rhs, Step.Pop, stack2, storeRight)
        fiberRight.resume()
        becomeWithSameEnv(fiberLeft)
        loopComp(lhs, Step.Pop, stack2, storeLeft)
      else
        //// Must have been cancelled meanwhile
        loopCancel(stack, store)
    else
      //// Fallback to sequential
      val comp2 = lhs ||! rhs
      loopComp(comp2, step, stack, store)


  final def intrinsicOrSeq[A, U](lhs: A !! U, rhsFun: () => A !! U): Tag =
    val step = savedStep
    val stack = savedStack
    val store = savedStore
    //-------------------
    val fiberLeft = currentFiber.createChild(Bits.OrSeq)
    if currentFiber.tryStartRaceOfOne(fiberLeft, currentEnv.isCancellable) then
      val (storeDown, storeLeft) = OpCascaded.fork(stack, store)
      currentFiber.suspendForRace(rhsFun, step, stack, storeDown)
      val stack2 = stack.makeFork
      becomeWithSameEnv(fiberLeft)
      loopComp(lhs, Step.Pop, stack2, storeLeft)
    else
      //// Must have been cancelled meanwhile
      loopCancel(stack, store)


  final def intrinsicHandle(body: AnyComp, prompt: Prompt, initial: Any): Tag =
    val step = savedStep
    val stack = savedStack
    val store = savedStore
    //-------------------
    for sig <- prompt.signatures do
      if stack.containsSignature(sig) then
        panic(s"Unsupported feature: shadowing effect ${sig}.")
    val (stack2, store2) = OpPush.pushBase(stack, store, step, prompt, initial.asLocal)
    loopComp(body, Step.Pop, stack2, store2)


  final def intrinsicSnap[A, U](body: A !! U): Tag =
    val step = savedStep
    val stack = savedStack
    val store = savedStore
    //-------------------
    val (stack2, store2) = OpPush.pushNestedIO(stack, store, step, Local.void, FrameKind.guard)
    loopComp(body, Step.Pop, stack2, store2)


  final def intrinsicUnsnap[A, U](snap: Snap[A]): Tag =
    val step = savedStep
    val stack = savedStack
    val store = savedStore
    //-------------------
    //@#@TODO forbid uncancelling, it wouldnt work correctly anyway
    (snap: @unchecked) match
      case Snap.Success(payload2)         => loopStep(payload2, step, stack, store)
      case Snap.Failure(payload2)         => loopStep(payload2, Step.Throw, stack, store)
      case Snap.Aborted(payload2, prompt) => loopStep(payload2, Step.abort(prompt), stack, store)
      case Snap.Cancelled =>
        //@#@THOV It should be harmless to self-cancel a fiber, even when it's uncancellable?
        currentFiber.cancelBySelf()
        loopCancel(stack, store)


  final def intrinsicEnvAsk[A](fun: Env => A): Tag =
    val step = savedStep
    val stack = savedStack
    val store = savedStore
    //-------------------
    val value = fun(currentEnv)
    loopStep(value, step, stack, store)


  final def intrinsicEnvMod[A, U](fun: Env => Env, body: A !! U): Tag =
    val step = savedStep
    val stack = savedStack
    val store = savedStore
    //-------------------
    val env2 = fun(currentEnv)
    if currentEnv == env2 then
      loopComp(body, step, stack, store)
    else
      val (stack2, store2) = OpPush.pushNestedIO(stack, store, step, env2.asLocal, FrameKind.plain)
      this.currentEnv = env2
      loopComp(body, Step.Pop, stack2, store2)


  final def intrinsicForkFiber[A, U](warp0: Warp | Null, comp: A !! U, name: String, callback: (Zipper.Untyped => Unit) | Null = null): Tag =
    val step = savedStep
    val stack = savedStack
    val store = savedStore
    //-------------------
    val warp = if warp0 != null then warp0.nn.asImpl else currentEnv.currentWarp.nn
    val (storeDown, storeFork) = OpCascaded.fork(stack, store)
    val stackFork = stack.makeFork
    val child = FiberImpl.createExplicit(warp, name, callback)
    child.suspendComp(comp, Step.Pop, stackFork, storeFork)
    if warp.tryAddFiber(child) then
      child.resume()
      loopStep(child, step, stack, storeDown)
    else
      child.suspendAsCancelled()
      loopStep(child, step, stack, store)


  final def intrinsicAwaitFiber[A, U](fiber: Fiber.Untyped, isCancel: Boolean, isVoid: Boolean): Tag =
    val step = savedStep
    val stack = savedStack
    val store = savedStore
    //-------------------
    val waitee = fiber.asImpl
    if currentFiber != waitee then
      val notifyTag = if isVoid then Tag.NotifyUnit else Tag.NotifyZipper
      currentFiber.suspend(notifyTag, waitee, step, stack, store)
      val tried =
        if isCancel
        then waitee.tryGetCancelledBy(currentFiber, currentEnv.isCancellable)
        else waitee.tryGetAwaitedBy(currentFiber, currentEnv.isCancellable)
      tried match
        case Bits.WaiterSubscribed => ThreadDisowned
        case Bits.WaiterAlreadyCancelled =>
          currentFiber.clearSuspension()
          loopCancel(stack, store)
        case Bits.WaiteeAlreadyCompleted =>
          currentFiber.clearSuspension()
          val payload2 = if isVoid then () else waitee.getOrMakeZipper
          loopStep(payload2, step, stack, store)
    else
      //// Ignoring `isCancellable` bcoz cancelling is by-self
      if isCancel then
        currentFiber.cancelBySelf()
        loopCancel(stack, store)
      else
        val zombie = new Blocker.Zombie(currentFiber)
        currentFiber.suspendStep(null, step, stack, store)
        if currentFiber.tryGetBlocked(zombie, currentEnv.isCancellable) then
          ThreadDisowned
        else
          currentFiber.clearSuspension()
          loopCancel(stack, store)


  final def intrinsicCurrentFiber(): Tag =
    val step = savedStep
    val stack = savedStack
    val store = savedStore
    //-------------------
    loopStep(currentFiber, step, stack, store)


  final def intrinsicSpawnWarp[A, U](exitMode: Warp.ExitMode, body: A !! (U & Warp), name: String): Tag =
    val step = savedStep
    val stack = savedStack
    val store = savedStore
    //-------------------
    val warp = new WarpImpl(currentFiber, currentEnv.currentWarp, name, exitMode)
    val env2 = currentEnv.copy(currentWarp = warp)
    val (stack2, store2) = OpPush.pushNestedIO(stack, store, step, env2.asLocal, FrameKind.warp)
    this.currentEnv = env2
    loopComp(body, Step.Pop, stack2, store2)


  final def intrinsicAwaitWarp(warp0: Warp, isCancel: Boolean): Tag =
    val step = savedStep
    val stack = savedStack
    val store = savedStore
    //-------------------
    val warp = warp0.asImpl
    currentFiber.suspendStep((), step, stack, store)
    val tried =
      if isCancel
      then warp.tryGetCancelledBy(currentFiber, currentEnv.isCancellable)
      else warp.tryGetAwaitedBy(currentFiber, currentEnv.isCancellable)
    tried match
      case Bits.WaiterSubscribed => ThreadDisowned
      case Bits.WaiterAlreadyCancelled =>
        currentFiber.clearSuspension()
        loopCancel(stack, store)
      case Bits.WaiteeAlreadyCompleted =>
        currentFiber.clearSuspension()
        loopStep((), step, stack, store)


  final def intrinsicAsync[A](callback: (Either[Throwable, A] => Unit) => Unit): Tag =
    currentFiber.suspendStep(null, savedStep, savedStack, savedStore)
    callback(currentFiber)
    ThreadDisowned


  final def intrinsicBlocking[A, B](thunk: () => A, isAttempt: Boolean): Tag =
    val step = savedStep
    val stack = savedStack
    val store = savedStore
    //-------------------
    val blocker = new Blocker.Interruptible(currentFiber, thunk, isAttempt)
    currentFiber.suspendStep(null, step, stack, store)
    if currentFiber.tryGetBlocked(blocker, currentEnv.isCancellable) then
      blocker.block()
      ThreadDisowned
    else
      currentFiber.clearSuspension()
      loopCancel(stack, store)


  final def intrinsicSleep(length: Long, unit: TimeUnit = TimeUnit.MILLISECONDS): Tag =
    val step = savedStep
    val stack = savedStack
    val store = savedStore
    //-------------------
    val blocker = new Blocker.Sleeper(currentFiber)
    currentFiber.suspendStep((), step, stack, store)
    if currentFiber.tryGetBlocked(blocker, currentEnv.isCancellable) then
      blocker.sleep(length, unit)
      ThreadDisowned
    else
      currentFiber.clearSuspension()
      loopCancel(stack, store)


  final def intrinsicSuppress[A, U](body: A !! U, delta: Int): Tag =
    val step = savedStep
    val stack = savedStack
    val store = savedStore
    //-------------------
    val n1 = currentEnv.suppressions
    val n2 = 0.max(n1 + delta)
    if n1 == n2 then
      loopComp(body, step, stack, store)
    else
      val env2 = currentEnv.copy(suppressions = n2)
      val (stack2, store2) = OpPush.pushNestedIO(stack, store, step, env2.asLocal, FrameKind.suppress)
      this.currentEnv = env2
      if cancellationCheck() then
        loopCancel(stack2, store2)
      else
        loopComp(body, Step.Pop, stack2, store2)


  final def intrinsicExecOn[A, U](exec: Executor, body: A !! U): Tag =
    val step = savedStep
    val stack = savedStack
    val store = savedStore
    //-------------------
    if currentEnv.executor == exec then
      loopComp(body, step, stack, store)
    else
      val env2 = currentEnv.copy(executor = exec)
      val (stack2, store2) = OpPush.pushNestedIO(stack, store, step, env2.asLocal, FrameKind.exec)
      currentFiber.suspendComp(body, Step.Pop, stack2, store2)
      currentFiber.resume()
      ThreadDisowned


  final def intrinsicYield: Tag =
    val step = savedStep
    val stack = savedStack
    val store = savedStore
    //-------------------
    currentFiber.suspendStep((), step, stack, store)
    Tag.Yield


  final def intrinsicAwaitOnceVar[A](ovar0: OnceVar.Get[A]): Tag =
    val step = savedStep
    val stack = savedStack
    val store = savedStore
    //-------------------
    val ovar = ovar0.asImpl
    val value = ovar.theContent
    if OnceVarImpl.Empty != value then
      loopStep(value, step, stack, store)
    else
      currentFiber.suspend(Tag.NotifyOnceVar, ovar, step, stack, store)
      ovar.tryGetAwaitedBy(currentFiber, currentEnv.isCancellable) match
        case Bits.WaiterSubscribed => ThreadDisowned
        case Bits.WaiterAlreadyCancelled =>
          currentFiber.clearSuspension()
          loopCancel(stack, store)
        case Bits.WaiteeAlreadyCompleted =>
          currentFiber.clearSuspension()
          val value = ovar.theContent
          loopStep(value, step, stack, store)


  final def intrinsicAwaitCountDownLatch(latch: CountDownLatch): Tag =
    val step = savedStep
    val stack = savedStack
    val store = savedStore
    //-------------------
    currentFiber.suspendStep((), step, stack, store)
    latch.asImpl.tryGetAwaitedBy(currentFiber, currentEnv.isCancellable) match
      case Bits.WaiterSubscribed => ThreadDisowned
      case Bits.WaiterAlreadyCancelled =>
        currentFiber.clearSuspension()
        loopCancel(stack, store)
      case Bits.WaiteeAlreadyCompleted =>
        currentFiber.clearSuspension()
        loopStep((), step, stack, store)


  final def intrinsicAwaitCyclicBarrier(barrier: CyclicBarrier): Tag =
    val step = savedStep
    val stack = savedStack
    val store = savedStore
    //-------------------
    currentFiber.suspendStep((), step, stack, store)
    barrier.asImpl.tryGetAwaitedBy(currentFiber, currentEnv.isCancellable) match
      case Bits.WaiterSubscribed => ThreadDisowned
      case Bits.WaiterAlreadyCancelled =>
        currentFiber.clearSuspension()
        loopCancel(stack, store)
      case Bits.WaiteeAlreadyCompleted =>
        currentFiber.clearSuspension()
        loopStep((), step, stack, store)


  final def intrinsicAcquireMutex(mutex: Mutex): Tag =
    val step = savedStep
    val stack = savedStack
    val store = savedStore
    //-------------------
    currentFiber.suspendStep((), step, stack, store)
    mutex.asImpl.tryGetAcquiredBy(currentFiber, currentEnv.isCancellable) match
      case Bits.WaiterSubscribed => ThreadDisowned
      case Bits.WaiterAlreadyCancelled =>
        currentFiber.clearSuspension()
        loopCancel(stack, store)
      case Bits.WaiteeAlreadyCompleted =>
        currentFiber.clearSuspension()
        loopStep((), step, stack, store)


  final def intrinsicAcquireSemaphore(semaphore: Semaphore, count: Long): Tag =
    val step = savedStep
    val stack = savedStack
    val store = savedStore
    //-------------------
    currentFiber.suspend(Tag.NotifyUnit, count, step, stack, store)
    semaphore.asImpl.tryGetAcquiredBy(currentFiber, currentEnv.isCancellable, count) match
      case Bits.WaiterSubscribed => ThreadDisowned
      case Bits.WaiterAlreadyCancelled =>
        currentFiber.clearSuspension()
        loopCancel(stack, store)
      case Bits.WaiteeAlreadyCompleted =>
        currentFiber.clearSuspension()
        loopStep((), step, stack, store)


  final def intrinsicGetChannel[A](channel: Channel.Get[A]): Tag =
    val step = savedStep
    val stack = savedStack
    val store = savedStore
    //-------------------
    currentFiber.suspendStep(null, step, stack, store)
    val (code, value) = channel.asImpl.tryGetBy(currentFiber, currentEnv.isCancellable)
    code match
      case Bits.WaiterSubscribed => ThreadDisowned
      case Bits.WaiterAlreadyCancelled =>
        currentFiber.clearSuspension()
        loopCancel(stack, store)
      case Bits.WaiteeAlreadyCompleted =>
        currentFiber.clearSuspension()
        loopStep(value, step, stack, store)


  final def intrinsicPutChannel[A](channel: Channel.Put[A], value: A): Tag =
    val step = savedStep
    val stack = savedStack
    val store = savedStore
    //-------------------
    currentFiber.suspend(Tag.NotifyUnit, value, step, stack, store)
    channel.asImpl.tryPutBy(currentFiber, currentEnv.isCancellable) match
      case Bits.WaiterSubscribed => ThreadDisowned
      case Bits.WaiterAlreadyCancelled =>
        currentFiber.clearSuspension()
        loopCancel(stack, store)
      case Bits.WaiteeAlreadyCompleted =>
        currentFiber.clearSuspension()
        loopStep((), step, stack, store)


  //-------------------------------------------------------------------
  // Misc
  //-------------------------------------------------------------------


  final def becomeClear(): Unit =
    currentFiber = null.asInstanceOf[FiberImpl]
    currentEnv = null.asInstanceOf[Env]


  final def become(fiber: FiberImpl): Unit =
    currentFiber = fiber
    refreshEnv(fiber.suspendedStack.nn, fiber.suspendedStore.nn) 


  final def getCurrentFiber: FiberImpl = currentFiber


  private final def becomeWithSameEnv(fiber: FiberImpl): Unit =
    currentFiber = fiber


  private final def refreshEnv(stack: Stack, store: Store): Unit =
    currentEnv = OpPush.findTopmostEnv(stack, store)


  private final def cancellationCheck(): Boolean =
    currentFiber.cancellationCheck(currentEnv.isCancellable)


  private final def clearSaved(): Unit =
    this.savedPayload = null
    this.savedStep = null.asInstanceOf[Step]
    this.savedStack = null.asInstanceOf[Stack]
    this.savedStore = null.asInstanceOf[Store]




© 2015 - 2024 Weber Informatics LLC | Privacy Policy