チャンネル | 目次 |
チャンネルは同じアクターに送信される異なる型のメッセージの処理を簡略化する。チャンネルの継承階層は OutputChannel
と InputChannel
に分かれる。
OutputChannel
はメッセージの送信に用いられる。OutputChannel
out
は以下の演算をサポートする。
out ! msg
。非同期で msg
を out
に送信する。アクターに直接 msg
が送信された場合と同様に、送信アクターの参照も通信される。out forward msg
。非同期で msg
を out
に転送する。アクターに直接 msg
が転送された場合と同様に、送信アクターが限定される。out.receiver
。 out
チャンネルに送信されるメッセージを受信する唯一のアクターを返す。out.send(msg, from)
。非同期で msg
を out
に、メッセージの送信者を from
として送信する。OutputChannel
トレイトは、( !
、forward
、send
を用いて)チャンネルに送信できるメッセージの型を型パラメータとして持つことに注意してほしい。この型パラメータは反変 (contravariant) だ:
trait OutputChannel[-Msg]
アクターは InputChannel
からメッセージを受信できる。OutputChannel
同様に、InputChannel
トレイトは、チャンネルから受信できるメッセージの型を型パラメータとしてを持つ。 この型パラメータは共変 (covariant) だ:
trait InputChannel[+Msg]
InputChannel[Msg]
in
は以下の演算をサポートする。
in.receive { case Pat1 => ... ; case Patn => ... }
(in.receiveWithin
、も同様)。in
からメッセージを受信する。入力チャンネルに対する receive
の呼び出しは標準的なアクターに対する receive
演算と同じ意味を持つ。唯一の違いは、引数として渡される部分関数が、PartialFunction[Msg, R]
型をとることだ(R
は receive
の戻り値型)。in.react { case Pat1 => ... ; case Patn => ... }
(in.reactWithin
も同様)。 イベントによる react
を用いて in
からメッセージを受信する。アクターの react
と同様に、戻り値型は呼び出しが戻らないことを示す Nothing
だ。上記の receive
同様に、引数として渡される部分関数の型は、PartialFunction[Msg, Unit]
に再定義されている。チャンネルは具象クラス (concrete class) である Channel
を用いて作成される。これは InputChannel
と OutputChannel
の両方を継承する。チャンネルは複数のアクターから見えるようなスコープに置くか、メッセージの中に入れて送信することで共有できる。
以下に、スコープによる共有の具体例を示す。
actor { var out: OutputChannel[String] = null val child = actor { react { case "発進" => out ! "おはよう" } } val channel = new Channel[String] out = channel child ! "発進" channel.receive { case msg => println(msg.length) } }
この例を実行するとコンソールに文字列の "5"
が表示される。child
アクターは OutputChannel[String]
の out
にのみアクセスがあることに注意してほしい。メッセージを受信することもできる channel
への参照は、child
からは見えなくなっている。しかし、child
がメッセージを送信する前に、出力チャンネルがなんらかのチャンネル実装により初期化されていることに気を使わなくてはならない。これは、"発進"
メッセージにより行われている。channel.receive
を用いて channel
からメッセージを受信した後、msg
が String
型であることを利用して、例えば length
メンバーを使うことができる。
チャンネルを共有するもう一つの方法として、メッセージの中に入れて送信するというものがある。次の例で、これを示す。
case class ReplyTo(out: OutputChannel[String]) val child = actor { react { case ReplyTo(out) => out ! "おはよう" } } actor { val channel = new Channel[String] child ! ReplyTo(channel) channel.receive { case msg => println(msg.length) } }
OutputChannel[String]
への参照を配布するためのメッセージ型として ReplyTo
ケースクラスを使う。child
アクターが ReplyTo
メッセージを受信すると、それはメッセージ内に格納された出力チャンネルにメッセージを送信する。二番目のアクターは、先ほどの例と同様にそのチャンネルからメッセージを受信する。
チャンネル | 目次 |