咳といいます。

一年以上前の話題なのです

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