アクタモデルによるプログラミング

Scala でアクタ(scala.actor.Actor)を使ってプログラミングしていると、他のコンポーネントというかアクタに処理を依頼したあと、処理結果が帰ってくるまで待つような書き方をしなくなってくる。
一応、Actor では「!?」を使ってメッセージそ送信することで、相手の返信を待つようなことが出来るんだけど、相手が返信しなかったりすると、待ちっぱなしになってしまう。
あるメッセージは返信を期待し、他のメッセージは期待しないとかだと混乱するのもあってか、今のところメッセージの送信だけする「!」しか使ってない。

処理結果が必要な場合は以下みたいに、自身のアクタオブジェクトをメッセージに含めて、相手先からメッセージを送ってもらってる。

// メッセージ
case class Register(sender: Actor, address: String)
case class RegisterSuccess(address: String)
case class RegisterFailure(address: String)

// 登録依頼者のアクタ
class ClientActor(registrar: Actor) extends Actor {
  def act(): Unit = {
    loop { reactWithin(1000) {// 1秒に1回登録しようとする
      case TIMEOUT => 
        // 登録処理を依頼するだけ。完了まで待たない
        registrar ! Register(this, "foo@bar.baz")
      case RegisterSuccess(address) => // 登録成功
      case RegisterFailure(address) => // 登録失敗
    }}
  }
}

// 登録担当者のアクタ
class RegistrarActor extends Actor {
  def act(): Unit = {
    loop { react {
      case Register(sender, address) =>
        // 登録処理
        val success = .....;

        if (success)
          sender ! RegisterSuccess(address)
        else
          sender ! RegisterFailure(address)
    }}
  }
}

チュートリアルにあったオークションのサンプルも、たしかこんな風にやってた。
メッセージを非同期で対象性のあるものだと考えるとしっくりくる。
メッセージハブ的*1なアクタがいれば、メッセージにアクタを含める必要もない・・・けど、微妙に分かりづらくなりそう。

この書き方だと、他のアクタで処理が終わるのを待つことがないので、各アクタがちゃんと並列に実行される(と思う)。
ただ、メッセージのやり取りのみで協調動作させるため、複雑になってくると処理を理解しづらいかも。

*1:メッセージのブロードキャストとかするアクタ、アクタをグループ化&階層化するとか