けいじゅ@日本ラショナルソフトウェアです. In [ruby-list :13029 ] the message: "[ruby-list:13029] Re: ", on Mar/19 18:54(JST) Mitsuru Oshima writes: >おおしまです。 >あと、大きな問題ではないと思うのですが、 # 大きな問題でないってこともないと思いますけどね(^^;;; >foo = Object.new >WeakRef.new(foo) >WeakRef.new(foo) > >とすると、メモリリークが起きてしまうような気がします。 >(先に作られたリファレンスのidのエントリが残ってしまう。) >すでに存在する場合にはそれを返すようなメソッドが >あった方がよいのでは? たとえば、 > >def WeakRef.getRef(obj) > rid = ID_MAP[obj.__id__] > if rid > return ObjectSpace._id2ref(rid) > elsif > return WeakRef.new(obj) > end >end >のような。このままだとthread safeでなかったり、途中でGCされたりすると >こまってしまいますが、、、 これだと, WeakRefを使いたい時には WeakRef.getRefを使えってことになりま すね... 以下の方が嬉しいかな. def WeakRef.new(obj) rid = ID_MAP[obj.__id__] if rid return ObjectSpace._id2ref(rid) elsif return super end end または, 以下のような感じにしても良いかも: class WeakRef<Delegator class RefError<StandardError end ID_MAP = {} ID_REV_MAP = {} ObjectSpace.add_finalizer(lambda{|id| rids = ID_MAP[id] if rids for rid in rids ID_REV_MAP[rid] = nil end ID_MAP[id] = nil end rid = ID_REV_MAP[id] if rid ID_REV_MAP[id] = nil ID_MAP[rid] = nil end }) def initialize(orig) super @__id = orig.__id__ ObjectSpace.call_finalizer orig ObjectSpace.call_finalizer self ID_MAP[@__id] = [] unless ID_MAP[@__id] ID_MAP[@__id].concat self.__id__ ID_REV_MAP[self.id] = @__id end __ ................................石塚 圭樹@日本ラショナルソフトェア... ----------------------------------->> e-mail: keiju / rational.com <<---