1 # Weak Reference class that does not bother GCing.
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)
15 class WeakRef < Delegator
17 class RefError < StandardError
20 @@id_map = {} # obj -> [ref,...]
21 @@id_rev_map = {} # ref -> obj
23 @@final = lambda {|id|
28 @@id_rev_map.delete(rid)
32 rid = @@id_rev_map[id]
34 @@id_rev_map.delete(id)
35 @@id_map[rid].delete(id)
36 @@id_map.delete(rid) if @@id_map[rid].empty?
42 @__id = orig.object_id
43 ObjectSpace.define_finalizer orig, @@final
44 ObjectSpace.define_finalizer self, @@final
46 @@id_map[@__id] = [] unless @@id_map[@__id]
48 @@id_map[@__id].push self.object_id
49 @@id_rev_map[self.object_id] = @__id
54 unless @@id_rev_map[self.object_id] == @__id
55 Kernel::raise RefError, "Invalid Reference - probably recycled", Kernel::caller(2)
58 ObjectSpace._id2ref(@__id)
60 Kernel::raise RefError, "Invalid Reference - probably recycled", Kernel::caller(2)
67 @@id_rev_map[self.object_id] == @__id
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)