Ruby: Revactor

RevactorをRuby1.9.1で試したところ単純に理解しきれないところがあったのでまとめておく。
まずgemを用いたインストール。とは言ってもgem自体になれていないのでこちらのサイトを参考にさせて頂いた。id:taigou:20090202:1233579475

$ gem sources -a http://gems.github.com
$ gem install rev
$ gem install revactor

READMEにあるサンプルプログラムを動かしてみる。

require 'revactor'
myactor = Actor.spawn do
  Actor.receive do |filter|
    filter.when(:dog) { puts "I got a dog!" }
  end
end
myactor << :dog

"I got a dog!"と表示されるのを期待したが出ない。いろいろ調べると同じ問題をNewsgroupで聞いている人がいた。http://www.rhinocerus.net/forum/lang-ruby/68602-rev-actor-tcp-monkey-patching.html
最後に

Actor.sleep(0)

を付け加えれば、確かにきちんと表示されるようになった。Newsgroupの議論によれば

When doing anything with Actors, just remember you're "queuing up"
operations which will run later... later being whenever you call
Actor.receive. Actor.receive is the only way to defer control to other
Actors (keeping in mind Actor.sleep is just shorthand for Actor.receive)

上の例だとmyactorはspawnされただけなので、メインスレッドから何らかの形でActor.receiveが呼び出されないとコントロールがActor側に渡されないという事らしい。次のような形でも動作する。

parent = Actor.current
myactor = Actor.spawn do
  Actor.receive do |filter|
    filter.when(:dog) {
      puts "I got a dog!"
      parent << :foo
      }
  end
end
myactor << :dog
Actor.receive do |f|
  f.when(:foo)
end

サンプルとしては、tools/messaging_throughput.rb がより分かりやすいと思われる。
この後、よーしお父さんmongrelでベンチとるぞ、と意気込んだものの、mongrelのbuildに失敗する。Ruby1.9との相性が良くないみたいだ。1.9必須のrevactorのREADMEにはmongrelとの親和性の良さをアピールしているんだけど。。とりあえずmongrelやpassengerで試す前に、次はrevactorをsocketで試してみよう。