![]() |
![]() |
![]() |
チャンネル | 目次 |
チャンネルは同じアクターに送信される異なる型のメッセージの処理を簡略化する。チャンネルの継承階層は 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 メッセージを受信すると、それはメッセージ内に格納された出力チャンネルにメッセージを送信する。二番目のアクターは、先ほどの例と同様にそのチャンネルからメッセージを受信する。
![]() |
![]() |
![]() |
チャンネル | 目次 |