けいじゅ@日本ラショナルソフトウェアです.

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 <<---