Skip to content

Instantly share code, notes, and snippets.

@seki
Created May 31, 2009 18:35
Show Gist options
  • Save seki/120982 to your computer and use it in GitHub Desktop.
Save seki/120982 to your computer and use it in GitHub Desktop.
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
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
if __FILE__ == $0
class Foo
def initialize
@ns = AsyncNotificationCenter.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
AsyncNotificationCenter.instance.flush
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment