Class: Universa::WeakReference

Inherits:
Object
  • Object
show all
Defined in:
lib/universa/weak_reference.rb

Overview

The smarter and safer weak reference than a standard one. It keeps object_id even if it is GC’d and can create a hard reference when possible. Some code borrowed from github.com/ruby-concurrency/ref.

Note there is no alive? method because it is not thread safe. Use the safe approach:

weak = WeakReference.new(something)
hard = weak.get
if hard
   # we got safe reference in +hard+
end

or, scala/kotlin-style:

weak.let { |object|
  object.do_somethinf
}

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(object) ⇒ WeakReference

Create weak reference for a given object



29
30
31
32
# File 'lib/universa/weak_reference.rb', line 29

def initialize(object)
  @referenced_object_id = object.__id__
  @weakref = WeakRef.new(object)
end

Instance Attribute Details

#referenced_object_idObject (readonly)

ruby object it of the referenced object. Available also after object is recycled.



26
27
28
# File 'lib/universa/weak_reference.rb', line 26

def referenced_object_id
  @referenced_object_id
end

Instance Method Details

#getObject

Get the strong reference unless it is already reclaimed.

Returns:

  • (Object)

    har reference to the source object or nil



49
50
51
52
53
54
55
56
57
58
# File 'lib/universa/weak_reference.rb', line 49

def get
  @weakref.__getobj__
rescue => e
  # Jruby implementation uses RefError while MRI uses WeakRef::RefError
  if (defined?(RefError) && e.is_a?(RefError)) || (defined?(::WeakRef::RefError) && e.is_a?(::WeakRef::RefError))
    nil
  else
    raise e
  end
end

#let { ... } ⇒ Object

Call the block passing it hard ref to the object if it is not yet recycled

Yields:

  • object if it is not recycled

Returns:

  • what the block returned or nil



38
39
40
41
42
43
44
# File 'lib/universa/weak_reference.rb', line 38

def let
  if (hardref = object.get)
    yield hardref
  else
    nil
  end
end