スケジューラ トップ フューチャ チャンネル 目次

チャンネル

チャンネルは同じアクターに送信される異なる型のメッセージの処理を簡略化する。チャンネルの継承階層は OutputChannelInputChannel に分かれる。

OutputChannel はメッセージの送信に用いられる。OutputChannel out は以下の演算をサポートする。

OutputChannel トレイトは、( !forwardsend を用いて)チャンネルに送信できるメッセージの型を型パラメータとして持つことに注意してほしい。この型パラメータは反変 (contravariant) だ:

trait OutputChannel[-Msg]

アクターは InputChannel からメッセージを受信できる。OutputChannel 同様に、InputChannel トレイトは、チャンネルから受信できるメッセージの型を型パラメータとしてを持つ。 この型パラメータは共変 (covariant) だ:

trait InputChannel[+Msg]

InputChannel[Msg] in は以下の演算をサポートする。

チャンネルの作成と共有

チャンネルは具象クラス (concrete class) である Channel を用いて作成される。これは InputChannelOutputChannel の両方を継承する。チャンネルは複数のアクターから見えるようなスコープに置くか、メッセージの中に入れて送信することで共有できる。

以下に、スコープによる共有の具体例を示す。

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 からメッセージを受信した後、msgString型であることを利用して、例えば 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 メッセージを受信すると、それはメッセージ内に格納された出力チャンネルにメッセージを送信する。二番目のアクターは、先ほどの例と同様にそのチャンネルからメッセージを受信する。


2010年11月30日

スケジューラ トップ フューチャ チャンネル 目次