From df058ea0e3e13ad52fd3a3490b1e3bd56db044b2 Mon Sep 17 00:00:00 2001 From: nobu Date: Tue, 13 Mar 2012 03:37:06 +0000 Subject: Bug #5350 * gc.c: add ObjectSpace::WeakMap. [ruby-dev:44565][Bug #5350] * lib/weakref.rb: use WeakMap instead of _id2ref. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@34995 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- lib/weakref.rb | 48 ++++++++++-------------------------------------- 1 file changed, 10 insertions(+), 38 deletions(-) (limited to 'lib/weakref.rb') diff --git a/lib/weakref.rb b/lib/weakref.rb index ee5444a584..78f88a3f12 100644 --- a/lib/weakref.rb +++ b/lib/weakref.rb @@ -1,5 +1,4 @@ require "delegate" -require 'thread' # Weak Reference class that allows a referenced object to be # garbage-collected. A WeakRef may be used exactly like the object it @@ -24,51 +23,24 @@ class WeakRef < Delegator class RefError < StandardError end - @@id_map = {} # obj -> [ref,...] - @@id_rev_map = {} # ref -> obj - @@mutex = Mutex.new - @@final = lambda {|id| - @@mutex.synchronize { - rids = @@id_map[id] - if rids - for rid in rids - @@id_rev_map.delete(rid) - end - @@id_map.delete(id) - end - rid = @@id_rev_map[id] - if rid - @@id_rev_map.delete(id) - @@id_map[rid].delete(id) - @@id_map.delete(rid) if @@id_map[rid].empty? - end - } - } + @@__map = ::ObjectSpace::WeakMap.new ## # Creates a weak reference to +orig+ def initialize(orig) - @__id = orig.object_id - ObjectSpace.define_finalizer orig, @@final - ObjectSpace.define_finalizer self, @@final - @@mutex.synchronize { - @@id_map[@__id] = [] unless @@id_map[@__id] - } - @@id_map[@__id].push self.object_id - @@id_rev_map[self.object_id] = @__id + case orig + when true, false, nil + @delegate_sd_obj = orig + else + @@__map[self] = orig + end super end def __getobj__ # :nodoc: - unless @@id_rev_map[self.object_id] == @__id - Kernel::raise RefError, "Invalid Reference - probably recycled", Kernel::caller(2) - end - begin - ObjectSpace._id2ref(@__id) - rescue RangeError - Kernel::raise RefError, "Invalid Reference - probably recycled", Kernel::caller(2) - end + @@__map[self] or defined?(@delegate_sd_obj) ? @delegate_sd_obj : + Kernel::raise(RefError, "Invalid Reference - probably recycled", Kernel::caller(2)) end def __setobj__(obj) # :nodoc: @@ -78,7 +50,7 @@ class WeakRef < Delegator # Returns true if the referenced object is still alive. def weakref_alive? - @@id_rev_map[self.object_id] == @__id + !!(@@__map[self] or defined?(@delegate_sd_obj)) end end -- cgit v1.2.3