Class: WeakRef

Inherits:
Delegator
  • Object
show all
Defined in:
lib/weakref.rb

Overview

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.

Usage:

foo = Object.new
foo = Object.new
p foo.to_s			# original's class
foo = WeakRef.new(foo)
p foo.to_s			# should be same class
ObjectSpace.garbage_collect
p foo.to_s			# should raise exception (recycled)

Defined Under Namespace

Classes: RefError

Constant Summary collapse

@@id_map =
{}
@@id_rev_map =

obj -> [ref,...] ref -> obj

{}
@@final =
lambda{|id|
  __old_status = Thread.critical
  Thread.critical = true
  begin
    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
  ensure
    Thread.critical = __old_status
  end
}

Instance Method Summary collapse

Constructor Details

#initialize(orig) ⇒ WeakRef

Create a new WeakRef from orig.



49
50
51
52
# File 'lib/weakref.rb', line 49

def initialize(orig)
  super
  __setobj__(orig)
end

Instance Method Details

#__getobj__Object

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



57
58
59
60
61
62
63
64
65
66
# File 'lib/weakref.rb', line 57

def __getobj__
  unless @@id_rev_map[self.__id__] == @__id
    raise RefError, "Illegal Reference - probably recycled", caller(2)
  end
  begin
    ObjectSpace._id2ref(@__id)
  rescue RangeError
    raise RefError, "Illegal Reference - probably recycled", caller(2)
  end
end

#__setobj__(obj) ⇒ Object



68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/weakref.rb', line 68

def __setobj__(obj)
  @__id = obj.__id__
  __old_status = Thread.critical
  begin
    Thread.critical = true
    unless @@id_rev_map.key?(self)
      ObjectSpace.define_finalizer obj, @@final
      ObjectSpace.define_finalizer self, @@final
    end
    @@id_map[@__id] = [] unless @@id_map[@__id]
  ensure
    Thread.critical = __old_status
  end
  @@id_map[@__id].push self.__id__
  @@id_rev_map[self.__id__] = @__id
end

#weakref_alive?Boolean

Returns true if the referenced object still exists, and false if it has been garbage collected.

Returns:

  • (Boolean)


87
88
89
# File 'lib/weakref.rb', line 87

def weakref_alive?
  @@id_rev_map[self.__id__] == @__id
end