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 が発生するので原因調査中です。このくらいであれば簡単に出来るのですけれど…。