From: Masatoshi SEKI Date: 2000-07-06T02:27:13+09:00 Subject: [ruby-list:23715] Re: Flyweight (Re: Integer[num]) 咳といいます。 一年以上前の話題なのです From: gotoken@math.sci.hokudai.ac.jp (GOTO Kentaro) Subject: [ruby-list:13690] Flyweight (Re: Integer[num]) Date: Tue, 13 Apr 1999 20:40:03 +0900 > # いま辞書索いたらFlyweightってフライ級のボクサーのコトだそうで > > -- gotoken > > # 蛇足:FlyweightFactory を実現する mix-in (よーするにハッシュ :-) ごとけんさんのコードを参考に ・GCされる … Hashが増え続けない ・Marshalできる … 生成時の引数のみを使って dump/load する ようなものを書いてみました。 おかしな部分があれば指摘してくださいませ。 # finalizer の中って Thread スイッチするのですか ?? # そうすると危険かも… # flyaway.rb require 'thread' require 'weakref' module FlyweightFactoryWeak def FlyweightFactoryWeak.append_features(mod) super mod.private_class_method :new mod.const_set("FW_HASHTABLE", {}) mod.const_set("FW_REV_TABLE", {}) mod.const_set("FW_MUTEX", Mutex.new) ObjectSpace.add_finalizer(lambda{|id| key = mod::FW_REV_TABLE[id] if key mod::FW_HASHTABLE[key] = nil mod::FW_REV_TABLE[id] = nil end }) def mod.[](*arg) self::FW_MUTEX.synchronize do begin key = (arg.size == 1) ? arg[0] : arg ref = self::FW_HASHTABLE[key] begin return ref[] if ref rescue WeakRef::RefError end obj = new(*arg) ref = WeakRef.new(obj) self::FW_HASHTABLE[key] = ref self::FW_REV_TABLE[obj.id] = key return obj ensure p self::FW_REV_TABLE if $DEBUG end end end def mod._load(s) self[*Marshal.load(s)] end end private def initialize(*arg) @fw_arg = arg end def _dump(port) Marshal.dump(@fw_arg, port) end end if __FILE__ == $0 class Foo include FlyweightFactoryWeak def initialize(name, message='hello') @name = name @message = message super # ! for dump/load trick end def to_s @name + ': ' + @message end end foo = Foo['mas'] bar = Foo['bar', 'world'] baz = Foo['bar', 'world'] p ['foo', foo.id] p ['bar', bar.id] p ['baz', baz.id] baz = nil ObjectSpace.garbage_collect foo = Foo['mas'] bar = Foo['bar', 'world'] baz = Foo['bar', 'world'] p ['foo', foo.id] p ['bar', bar.id] p ['baz', baz.id] bar = baz = nil ObjectSpace.garbage_collect foo = Foo['mas'] bar = Foo['bar', 'world'] baz = Foo['bar', 'world'] p ['foo', foo.id] p ['bar', bar.id] p ['baz', baz.id] foo = Marshal.load(Marshal.dump(bar)) p ['foo', foo.id] p ['bar', bar.id] end