Actor + CPS でコールバック関数を隠蔽する

勉強会第20回 - Scala勉強会 in 渋谷で久しぶりに発表するので下準備など。
ちょっとイロイロと手抜きコードですが… runTest メソッドだけ注目して下さい。switch メソッドを評価する度に Actor が切り替わります。

object Trampoline {
  import scala.actors.Actor
  import scala.actors.Actor.actor
  import scala.util.continuations.{reset, shift, cpsParam}

  def main (args: Array[String]) {
    TrampolineActorA.start
    TrampolineActorB.start

    reset(runTest())

    Thread.sleep(100)

    TrampolineActorA.stop
    TrampolineActorB.stop
  }

  def switch(otherSide: Actor): Unit @cpsParam[Unit, Unit] = {
    shift { k: (Unit => Unit) =>
      otherSide ! Execute(k)
    }
  }

  def runTest(): Unit @cpsParam[Unit, Unit] = {
    var n = 0
    println(n)

    switch(TrampolineActorA)
    n = n + 1
    println(n)

    switch(TrampolineActorB)
    n = n + 1
    println(n)

    switch(TrampolineActorA)
    n = n + 1
    println(n)

    switch(TrampolineActorB)
    n = n + 1
    println(n)
  }

  case class  Execute(f: Unit => Unit)
  case object Stop

  object TrampolineActorA extends Actor {
    def act() {
      loop {
        react {
          case Execute(f) => println("A"); f()
          case Stop       => exit()
          case unknown    => println(unknown)
        }
      }
    }

    def stop = this ! Stop
  }

  object TrampolineActorB extends Actor {
    def act() {
      loop {
        react {
          case Execute(f) => println("B"); f()
          case Stop       => exit()
          case unknown    => println(unknown)
        }
      }
    }

    def stop = this ! Stop
  }
}

ちなみに Remote Actor で同様の事を行うと、途中で java.lang.IllegalAccessError が発生するので原因調査中です。このくらいであれば簡単に出来るのですけれど…。