Skip to content

Instantly share code, notes, and snippets.

@plonk
Created February 17, 2013 07:03
Show Gist options
  • Select an option

  • Save plonk/4970511 to your computer and use it in GitHub Desktop.

Select an option

Save plonk/4970511 to your computer and use it in GitHub Desktop.
# -*- coding: utf-8 -*-
# my second attempt
require 'weakref'
module Event
# イベント名 Symbol をキーとして、
# 関心を示したオブジェクトへの WeakRef を持つ。
# オブジェクトは Event モジュールを include している。
@@event_objects_map = Hash.new
def Event.broadcast(name, *args)
interested = @@event_objects_map[name]
return unless interested # there's no-one interested in this type of event
# 関心を登録したオブジェクトのイベントハンドラーを
# 呼び出し、オブジェクトがすでに GC されていた場合は、
# リストから削除する。
interested.select! do |obj|
begin
obj.event_handler(name, *args)
true # 残す
rescue WeakRef::RefError
puts "recycled object in the registry. discarding"
false # 破棄する
end
end
end
# コールバック Proc を登録する
def register_callback(name, &block)
(@@event_objects_map[name] ||= []) << WeakRef.new(self)
@event_callback_map ||= {}
@event_callback_map[name] = block
end
def event_handler(event, *args)
map = @event_callback_map
return unless map
return unless map[event]
map[event].call(*args)
end
end
# ーーー 以下実例
class GameObject
include Event
end
a = GameObject.new
b = GameObject.new
# :some_event イベントにコールバックを登録する
a.register_callback(:some_event) do |i, j|
puts "a: #{i}, #{j}"
end
b.register_callback(:some_event) do |i, j|
puts "b: #{i}, #{j}"
end
# a を開放する
a = nil
GC.start
# b のコールバックだけが呼ばれるはず
Event.broadcast(:some_event, 123, 456)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment