Rindaをシングルスレッドで書けるかやってみたら書けそうな感じ。使い道ないけど!
まず、includeしたMonitorMixinの抜き方がわからなかったので、どうしようかと思ったけど、super()しなければ良いことに気づいた。
それから、synchronizeはただのyieldにした。
module Rinda class TupleSpace def initialize(period=5) @bag = TupleBag.new @read_waiter = TupleBag.new @take_waiter = TupleBag.new @notify_waiter = TupleBag.new @period = period @keeper = nil end def synchronize yield en
あとはMonitoroMixinのnew_condが書ければ良さそう。Rindaの使い方の場合、一つのtake/readを待つのは一つの実行主体だけなので、簡単なイベントを作って逃げることした。
module Rinda class Event def initialize @waiter = [] end def wait @waiter << Fiber.current.method(:resume) Fiber.yield end def signal return if @waiter.empty? # これは起こらないはず。たぶん。 @waiter.shift.call end end class TupleSpace def new_cond Event.new end end
忘れてたけど、notifyって操作があって(なんで追加したんだろう)がQueueを使ってるのでFiber用のQueueに交換。
module Bartender class Queue def initialize @reader = [] @queue = [] end def push(it) if @reader.empty? @queue << it else @reader.shift.call(it) end end def pop if @queue.empty? @reader << Fiber.current.method(:resume) Fiber.yield else @queue.shift end end end end module Rinda class NotifyTemplateEntry < TemplateEntry def initialize(place, event, tuple, expires=nil) ary = [event, Rinda::Template.new(tuple)] super(ary, expires) @queue = Bartender::Queue.new @done = false end end
動いたっぽい。でも持ってるテストはスレッドじゃないと試せないのばっかり。どうしよう。