Class: WeakRef

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

Overview

Weak Reference class that allows a referenced object to be garbage-collected.

A WeakRef may be used exactly like the object it references.

Usage:

foo = Object.new            # create a new object instance
p foo.to_s                  # original's class
foo = WeakRef.new(foo)      # reassign foo with WeakRef instance
p foo.to_s                  # should be same class
GC.start                    # start the garbage collector
p foo.to_s                  # should raise exception (recycled)

Example

With help from WeakRef, we can implement our own rudimentary WeakHash class.

We will call it WeakHash, since it’s really just a Hash except all of it’s keys and values can be garbage collected.

require 'weakref'

class WeakHash < Hash
  def []= key, obj
    super WeakRef.new(key), WeakRef.new(obj)
  end
end

This is just a simple implementation, we’ve opened the Hash class and changed Hash#store to create a new WeakRef object with key and obj parameters before passing them as our key-value pair to the hash.

With this you will have to limit your self to String keys, otherwise you will get an ArgumentError because WeakRef cannot create a finalizer for a Symbol. Symbols are immutable and cannot be garbage collected.

Let’s see it in action:

omg = "lol"
c = WeakHash.new
c['foo'] = "bar"
c['baz'] = Object.new
c['qux'] = omg
puts c.inspect
#=> {"foo"=>"bar", "baz"=>#<Object:0x007f4ddfc6cb48>, "qux"=>"lol"}

# Now run the garbage collector
GC.start
c['foo'] #=> nil
c['baz'] #=> nil
c['qux'] #=> nil
omg      #=> "lol"

puts c.inspect
#=> WeakRef::RefError: Invalid Reference - probably recycled

You can see the local variable omg stayed, although its reference in our hash object was garbage collected, along with the rest of the keys and values. Also, when we tried to inspect our hash, we got a WeakRef::RefError. This is because these objects were also garbage collected.

Defined Under Namespace

Classes: RefError

Constant Summary collapse

@@__map =
::ObjectSpace::WeakMap.new

Instance Method Summary collapse

Constructor Details

#initialize(orig) ⇒ WeakRef

Creates a weak reference to orig

Raises an ArgumentError if the given orig is immutable, such as Symbol, Fixnum, or Float.



82
83
84
85
86
87
88
89
90
# File 'lib/weakref.rb', line 82

def initialize(orig)
  case orig
  when true, false, nil
    @delegate_sd_obj = orig
  else
    @@__map[self] = orig
  end
  super
end

Instance Method Details

#__getobj__Object

:nodoc:



92
93
94
95
# File 'lib/weakref.rb', line 92

def __getobj__ # :nodoc:
  @@__map[self] or defined?(@delegate_sd_obj) ? @delegate_sd_obj :
    Kernel::raise(RefError, "Invalid Reference - probably recycled", Kernel::caller(2))
end

#__setobj__(obj) ⇒ Object

:nodoc:



97
98
# File 'lib/weakref.rb', line 97

def __setobj__(obj) # :nodoc:
end

#weakref_alive?Boolean

Returns true if the referenced object is still alive.

Returns:

  • (Boolean)


103
104
105
# File 'lib/weakref.rb', line 103

def weakref_alive?
  @@__map.key?(self) or defined?(@delegate_sd_obj)
end