diff options
author | ko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2006-12-31 15:02:22 +0000 |
---|---|---|
committer | ko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2006-12-31 15:02:22 +0000 |
commit | a3e1b1ce7ed7e7ffac23015fc2fde56511b30681 (patch) | |
tree | 7b725552a9a4ded93849ca2faab1b257f7761790 /lib/weakref.rb | |
parent | 3e7566d8fb5138bb9cd647e5fdefc54fc9803509 (diff) | |
download | ruby-a3e1b1ce7ed7e7ffac23015fc2fde56511b30681.tar.gz |
* Merge YARV
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11439 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'lib/weakref.rb')
-rw-r--r-- | lib/weakref.rb | 57 |
1 files changed, 20 insertions, 37 deletions
diff --git a/lib/weakref.rb b/lib/weakref.rb index 048f06f459..20e6a1b4d4 100644 --- a/lib/weakref.rb +++ b/lib/weakref.rb @@ -1,13 +1,6 @@ -require "delegate" - -# WeakRef is a class to represent a reference to an object that is not seen by -# the tracing phase of the garbage collector. This allows the referenced -# object to be garbage collected as if nothing is referring to it. Because -# WeakRef delegates method calls to the referenced object, it may be used in -# place of that object, i.e. it is of the same duck type. +# Weak Reference class that does not bother GCing. # # Usage: -# # foo = Object.new # foo = Object.new # p foo.to_s # original's class @@ -15,18 +8,21 @@ require "delegate" # p foo.to_s # should be same class # ObjectSpace.garbage_collect # p foo.to_s # should raise exception (recycled) -class WeakRef<Delegator - # RefError is raised if an object cannot be referenced by a WeakRef. - class RefError<StandardError +require "delegate" +require 'thread' + +class WeakRef < Delegator + + class RefError < StandardError end @@id_map = {} # obj -> [ref,...] @@id_rev_map = {} # ref -> obj + @@mutex = Mutex.new @@final = lambda {|id| - __old_status = Thread.critical - Thread.critical = true - begin + printf "final: %p\n", id + @@mutex.synchronize { rids = @@id_map[id] if rids for rid in rids @@ -40,20 +36,22 @@ class WeakRef<Delegator @@id_map[rid].delete(id) @@id_map.delete(rid) if @@id_map[rid].empty? end - ensure - Thread.critical = __old_status - end + } } - # Create a new WeakRef from +orig+. def initialize(orig) - __setobj__(orig) + @__id = orig.object_id + printf "orig: %p\n", @__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 super end - # Return the object this WeakRef references. Raises RefError if the object - # has been garbage collected. The object returned is the object to which - # method calls are delegated (see Delegator). def __getobj__ unless @@id_rev_map[self.object_id] == @__id Kernel::raise RefError, "Illegal Reference - probably recycled", Kernel::caller(2) @@ -64,24 +62,9 @@ class WeakRef<Delegator Kernel::raise RefError, "Illegal Reference - probably recycled", Kernel::caller(2) end end - def __setobj__(obj) - @__id = obj.object_id - ObjectSpace.define_finalizer obj, @@final - ObjectSpace.define_finalizer self, @@final - __old_status = Thread.critical - begin - Thread.critical = true - @@id_map[@__id] = [] unless @@id_map[@__id] - ensure - Thread.critical = __old_status - end - @@id_map[@__id].push self.object_id - @@id_rev_map[self.object_id] = @__id end - # Returns true if the referenced object still exists, and false if it has - # been garbage collected. def weakref_alive? @@id_rev_map[self.object_id] == @__id end |