* io.c (rb_open_file): encoding in mode string was ignored if perm is
[ruby-svn.git] / lib / weakref.rb
blobba39242445bd2facac9ad31969432d39c69ed2bf
1 # Weak Reference class that does not bother GCing.
3 # Usage:
4 #   foo = Object.new
5 #   foo = Object.new
6 #   p foo.to_s                  # original's class
7 #   foo = WeakRef.new(foo)
8 #   p foo.to_s                  # should be same class
9 #   ObjectSpace.garbage_collect
10 #   p foo.to_s                  # should raise exception (recycled)
12 require "delegate"
13 require 'thread'
15 class WeakRef < Delegator
17   class RefError < StandardError
18   end
20   @@id_map =  {}                # obj -> [ref,...]
21   @@id_rev_map =  {}            # ref -> obj
22   @@mutex = Mutex.new
23   @@final = lambda {|id|
24     @@mutex.synchronize {
25       rids = @@id_map[id]
26       if rids
27         for rid in rids
28           @@id_rev_map.delete(rid)
29         end
30         @@id_map.delete(id)
31       end
32       rid = @@id_rev_map[id]
33       if rid
34         @@id_rev_map.delete(id)
35         @@id_map[rid].delete(id)
36         @@id_map.delete(rid) if @@id_map[rid].empty?
37       end
38     }
39   }
41   def initialize(orig)
42     @__id = orig.object_id
43     ObjectSpace.define_finalizer orig, @@final
44     ObjectSpace.define_finalizer self, @@final
45     @@mutex.synchronize {
46       @@id_map[@__id] = [] unless @@id_map[@__id]
47     }
48     @@id_map[@__id].push self.object_id
49     @@id_rev_map[self.object_id] = @__id
50     super
51   end
53   def __getobj__
54     unless @@id_rev_map[self.object_id] == @__id
55       Kernel::raise RefError, "Invalid Reference - probably recycled", Kernel::caller(2)
56     end
57     begin
58       ObjectSpace._id2ref(@__id)
59     rescue RangeError
60       Kernel::raise RefError, "Invalid Reference - probably recycled", Kernel::caller(2)
61     end
62   end
63   def __setobj__(obj)
64   end
66   def weakref_alive?
67     @@id_rev_map[self.object_id] == @__id
68   end
69 end
71 if __FILE__ == $0
72 #  require 'thread'
73   foo = Object.new
74   p foo.to_s                    # original's class
75   foo = WeakRef.new(foo)
76   p foo.to_s                    # should be same class
77   ObjectSpace.garbage_collect
78   ObjectSpace.garbage_collect
79   p foo.to_s                    # should raise exception (recycled)
80 end