Scala Actor の reply が正しくできない問題は scala.actors.Channel が悪いのかも?

突っ込み大歓迎です。というか助けてください。

環境は、Mac OS 10.6.5, Scala 2.8.1.final, Java 1.6.0_22 となります。
検証用のコードは、Scala STM を試してみる その3 で使ったコードの修正版のこちらとなります。

STM と対比するために Actor のみを用いてカウンタのデモを書いたのですが、300 メッセージを超えた辺りから reply が失敗する状態となってしまいました。そこで reply 時に使われている Channel リストの操作に疑いを持ち、試しに返信用の Channel を作成し、それをメッセージで渡してみました。結果は、残念な事に 300 メッセージを超えた辺りから、Channel に送ったメッセージが取得できなくなりました。*1

最終的に、mailboxSize を確認すると良いのではないか?と考え、試しに下記を試してみたのですが…

object CounterInActor extends Actor {
// ..snip..
  def increment(): Int = {
    if (n < this.mailboxSize) {
      1
    } else {
      this !? Increment match {
        case n: Int => n
        case _      => 0
      }
    }
  }
// ..snip..

n の値を 0 にすると正しく動作しましたw;*2 300 近い Actor が、ほぼ同時にメッセージを送るので、確認した瞬間は 0 or 1 ですが、送り終わった後には 300 近辺の値になっていると思われます。そこで下記のように書き換えてみると…

object CounterInActor extends Actor {
// ..snip..
  def act() = loop {
    react {
      case Increment =>
        println(mailboxSize)
        counter += 1
        reply(counter)
// ..snip..
    }
  }
// ..snip..
}
--<400>--
0
310
309
308
307
306
305
304
303
302
301
300
299
298
385
384
383
382
381
380
379
378
377
376
375
374
373
372
371
370
369
368
367
366
365
364
363
362
361
360
359
358
357
356
// ..snip..

0 から 310 に跳ね上がってました。こうなって来ると、下記の workers を 200 個づつに分割して、間に Sleep を 50ms 入れる等の工夫が必要となります。

  def test (testCases: (String, Supervisor)*) {
// ..snip..
        val results = workers map {
          _.increment()
        } map {
          future => future()
        }
// ..snip..
  }

大元の検証コードに誤りがあると嬉しいのですが…。今の所、reply が必要な場合は、Client となる Actor の並列度に制限を行うか STM の使用を検討する事しか、私には思いつきませんでした。
うーん…、Channel の処理を深追いするしか無いかな。

*1:Future も試しましたが駄目でした。Future も内部的には Channel を使ってるらしいので、当たり前の結果ではありますが…。

*2:n = 1 だと駄目でした。