in debugger/src/main/scala/org.apache.daffodil.debugger.dap/Parse.scala [1363:1418]
def stopped(): IO[Control] =
for {
waiterArrived <- Deferred[IO, Unit]
state <- Ref[IO].of[State](AwaitingFirstAwait(waiterArrived))
} yield new Control {
def await(): IO[Boolean] =
for {
nextContinue <- Deferred[IO, Unit]
nextAwaitStarted <- Deferred[IO, Unit]
awaited <- state.modify {
case AwaitingFirstAwait(waiterArrived) =>
Stopped(nextContinue, nextAwaitStarted) -> waiterArrived
.complete(()) *> nextContinue.get.as(true)
case Running => Running -> IO.pure(false)
case s @ Stopped(whenContinued, nextAwaitStarted) =>
s -> nextAwaitStarted.complete(()) *> // signal next await happened
whenContinued.get.as(true) // block
}.flatten
} yield awaited
def step(): IO[Unit] =
for {
nextContinue <- Deferred[IO, Unit]
nextAwaitStarted <- Deferred[IO, Unit]
_ <- state.modify {
case s @ AwaitingFirstAwait(waiterArrived) =>
s -> waiterArrived.get *> step
case Running => Running -> IO.unit
case Stopped(whenContinued, _) =>
Stopped(nextContinue, nextAwaitStarted) -> (
whenContinued.complete(()) *> // wake up await-ers
nextAwaitStarted.get // block until next await is invoked
)
}.flatten
} yield ()
def continue(): IO[Unit] =
state.modify {
case s @ AwaitingFirstAwait(waiterArrived) =>
s -> waiterArrived.get *> continue
case Running => Running -> IO.unit
case Stopped(whenContinued, _) =>
Running -> whenContinued.complete(()).void // wake up await-ers
}.flatten
def pause(): IO[Unit] =
for {
nextContinue <- Deferred[IO, Unit]
nextAwaitStarted <- Deferred[IO, Unit]
_ <- state.update {
case Running => Stopped(nextContinue, nextAwaitStarted)
case s: AwaitingFirstAwait => s
case s: Stopped => s
}
} yield ()
}