0
votes

Okay I'm just about ready to give up on this.

I would like to save the state of a continuation (done using shift). However, the caveat is that the code AFTER the reset should not be executed. Consider the continuation being executed by worker thread, and should no longer be processed. The continuation is saved in a global list of continuations that can be resumed, and everything else after it is disregarded and should not execute.

The worker thread must survive (it cannot be aborted, or destroyed requiring the spinning up of a new thread).

reset {
  shift {
    (cont:Unit=>Unit) =>
      println(1)
      suspend() // how would I implement something like this?
      cont()
  }

  println(3)
}

println(2)

should yield

1

resuming the continuation should then yield

3
2

At the moment this does not seem possible at all, since the continuation is limited to the scope of the reset. But I figured I'll give StackOverflow one crack at it.


Edit: Basically... (maybe I should have put this earlier) I want to call a method, and suspend execution until it is ready to give me a result, and I want to achieve this over an evented loop, not thread synchronization.

1
Hm, I think it is not possible this way, but what's the problem to extend scope of reset? Do you know about cpsParam annotation, which allows to use shift inside method, which doesn't have reset at all, so that when call to this method appear inside some reset it will work expected way? Also you could use nested resets. - aemxdp
I can extend scope of reset, but the code that is being written within the reset will be done by 3rd parties, and thus I have no control over the code, and putting @cpsParam might not be feasible/convenient. - Daryl Teo

1 Answers

1
votes

I'm not sure, whether this is applicable to your situation, but here is example of how to mix multiple resets:

  type Proc = Unit => Unit

  val resume = reset {
    shift { k1: Proc =>
      reset {
        shift { k2: Proc =>
          println(1)
          () => k2(); k1() 
        }        
        println(3)
      }
    }
    println(2)
  }
  // 1

  resume()
  // 3
  // 2

Update: And here is how to use this with methods:

  def f(): Unit @cpsParam[Unit, () => Unit] = {
    println(0)

    shift { k1: Proc =>
      reset {
        shift { k2: Proc =>
          println(1)
          () => k2(); k1()
        }        
        println(2)
      }
    }

    println(3)
  }

  val continue = reset {
    println(-1)
    f()
    println(4)
  }

  println("...")

  continue()

Prints:

-1
0
1
...
2
3
4

And here is what to do if you don't want to suspend everything after call to f until the ending of reset:

  reset {
    println(-1)
    shift { k: Proc =>
      reset{f()}()
      k()
    }
    println(4)
  }

  println("...")

Prints:

-1
0
1
2
3
4
...