制御構造 トップ アクターのトレイト ReactorReplyReactorActor 目次

アクターのトレイト ReactorReplyReactorActor

Reactor トレイト

Reactor は、全てのアクターのトレイトの親トレイトだ。[訳注: Reactor とは「反応する者」という意味。] このトレイトを継承することで、メッセージを送受信するための基本的な機能を持つアクターを定義することができる。

Reactor の振る舞いは act メソッドを実装することで定義される。Reactorstart の呼び出しによって開始されると、act メソッドが実行される。start メソッドは Reactor を返すが、冪等 (idempotent) でもある。 冪等とは、既に開始されているアクターに対して start メソッドを何回呼び出しても何の影響もないことを意味する。

Reactor トレイトは、型パラメータ Msg を持つが、それはアクターが受信するメッセージの型を示す。

Reactor! メソッドの呼び出しは受信者にメッセージを送信する。

訳注: Scala では、全てのメソッドの呼び出しを中置記法、つまり a.!(msg)a ! msg のように表記できる。 そのため、メソッドを +* などの代数の演算子になぞらえて、「演算」(operation) というふうに言うことがある。
! によるメッセージの送信は非同期 (asynchronous)、つまり送信側のアクターは相手のメッセージ受信を待たずに即時に次の命令に続行することを意味する。例えば、a ! msg はメッセージ msga に送信する。全てのアクターはメールボックス (mailbox) を持ち、受信されたメッセージは処理されるまでそこにバッファリングされる。

Reactor トレイトは、forward メソッドも定義する。このメソッドは OutputChannel より継承され、! メソッドと同じ効果がある。 Reactor の子トレイト、特に ReplyReactor トレイトは、このメソッドをオーバーライドすることで暗黙の返信先 (implicit reply destination) を実現する(下記を参照)。

Reactorreact メソッドを用いてメッセージを受信する1react は、Msg 型のメッセージがアクターのメールボックスに到着した後どのように処理されるかを定義する PartialFunction[Msg, Unit] 型の引数を受け取る。 "おはよう" という文字列を受信することを待ち、挨拶を表示するアクターの具体例を以下に示す:

react {
  case "おはよう" => println("あ、おはようございます")
}

react の呼び出しは戻ってこない。 そのため、メッセージの受信後に実行すべきコードがあるならば、react に渡される部分関数の中に入るようにしなければならない。例えば、react の呼び出しを入れ子にすることで二つのメッセージを受信できる:

react {
  case Get(from) =>
    react {
      case Put(x) => from ! x    }
}

Reactor トレイトは、react を用いたプログラミングを簡略化する制御構造も提供する ( * を参照)。

終了と実行状態

Reactor の実行は、act メソッドが本文の最後まで完了することで終了する。Reactorexit メソッドを用いて明示的に終了することもできる。exit は常に例外を発生させるため、その戻り値型は Nothing だ。 この例外は内部で用いられるため、絶対に捕捉してはいけない。

終了した Reactor は、restart メソッドにより再起動できる。まだ終了していない Reactor に対して restart を呼び出すと、IllegalStateException が発生する。終了したアクターを再起動すると、act メソッドが再実行される。

Reactor は、アクターの現在の実行状態 (execution state) を Actor.State 列挙型として返す getState メソッドを定義する。開始前のアクターは Actor.State.New 状態にある。メッセージを待たずに実行できるアクターは Actor.State.Runnable 状態にある。メッセージを待機しながら一時停止してるアクターは Actor.State.Suspended 状態にある。終了したアクターは、Actor.State.Terminated 状態にある。

例外処理

exceptionHandler メンバーは、Reactor の全人生における例外処理を定義することを可能にする。

def exceptionHandler: PartialFunction[Exception, Unit]

exceptionHandler は、必要に応じて例外を処理する部分関数を返す。 Reactoract メソッドの本文の外へと例外が伝搬すると、 アクターが終了前に事後処理コードを実行できるように、その例外に対してこの部分関数が適用される。exceptionHandler の可視性は protected であることに注意。

exceptionHandler を用いた例外処理は、react を用いたプログラミングのための制御構造と相性がいい(* を参照)。exceptionHandler が返す部分関数により例外が処理されると、アクターの実行は現在の継続クロージャによって続行する。具体例としては:

Loop  react {
    case Msg(data) =>
      if (cond) // process data
      else throw new Exception("データを処理できません")
  }
}

この ReactorexceptionHandler をオーバーライドすると仮定すると、react の本文内で発生した例外が処理された後、アクターの実行は次のループ周回へと続行する。

ReplyReactor トレイト

ReplyReactor トレイトは Reactor[Any] を継承し、以下のメソッドを追加もしくはオーバーライドする:

その他、ReplyReactorActor.State.TimedSuspended という実行状態を追加する。 reactWithin を用いてメッセージを待機しながら一時停止してるアクターは Actor.State.TimedSuspended 状態にある。

Actor トレイト

Actor トレイトは ReplyReactor を継承し、以下のメンバーを追加またはオーバーライドする:

終了と実行状態

アクターの実行を終了するとき、以下の形態の exit を呼び出すことで終了理由を明示的に指定できる:

def exit(reason: AnyRef): Nothing

'normal シンボル以外の終了理由でアクターが終了した場合は、その終了理由ほ全てのリンクしたアクターに伝搬する。もしアクターが捕捉されなかった例外により終了した場合の終了理由は UncaughtException case class だ。

Actor トレイトは二つの実行状態を追加する。receive を用いてメッセージを待機しながら一時停止してるアクターは Actor.State.Blocked 状態にある。 receiveWithin を用いてメッセージを待機しながら一時停止してるアクターは Actor.State.TimedBlocked 状態にある。


2010年11月30日

制御構造 トップ アクターのトレイト ReactorReplyReactorActor 目次