@m_seki の

I like ruby tooから引っ越し

NotificationCenter

NSNotificationCenterを真似してみたくなったので書いてみた。使い道はあとで考える。TupleSpaceを借りてきたのであんまりあたまを使わなかった。

require 'rinda/tuplespace'
require 'singleton'

class NotificationCenter
  include Singleton

  class Handle
    def initialize; @removed = false; end
    def remove; @removed = true; end
    def removed?; @removed; end
  end

  def initialize
    @place = Rinda::TupleSpace.new
    @any = Object.new
  end

  def add(observer, message, event, object)
    object ||= @any
    @place.write([event, object, observer, message, Handle.new])
  end

  def remove(observer, message, event, object)
    object ||= @any
    tuple = @place.take([event, object, observer, message, nil], 0)
    tuple[4].removed
  rescue
  end

  def post(event, from, info=nil)
    dispatch(event, from, info)
  end

  def dispatch_one(from, info, tuple)
    event, ignore, observer, message, handle = tuple
    return if handle.removed?
    observer.send(message, event, from, info)
  end
  
  def dispatch(event, from, info)
    @place.read_all([event, from, nil, nil, nil]).each do |tuple|
      dispatch_one(from, info, tuple)
    end
    @place.read_all([event, @any, nil, nil, nil]).each do |tuple|
      dispatch_one(from, info, tuple)
    end
  end
end

if __FILE__ == $0
  class Foo
    def initialize
      @ns = NotificationCenter.instance
      @ns.add(self, :notify, :foo, self)
    end

    def notify(event, from, info)
      p event
      @ns.remove(self, :notify, :foo, self)
    end
    
    def change
      @ns.post(:foo, self)
    end
  end

  foo = Foo.new
  foo.change
  foo.change
end

通知を非同期に(あとで)送る版。
NSNotificationCenterって、通知は即座に送られるの?

require 'thread'

class AsyncNotificationCenter < NotificationCenter
  def initialize
    @queue = Queue.new
    super()
  end

  def post(event, from, info=nil)
    @queue.push([event, from, info])
  end

  def flush
    while ! @queue.empty?
      event, from, info = @queue.pop
      dispatch(event, from, info)
    end
  end
end

あとで読む。

たのしいCocoaプログラミング[Leopard対応版]

たのしいCocoaプログラミング[Leopard対応版]