Class: Farce::WeakValue

Inherits:
Object
  • Object
show all
Includes:
Abstract::Value, Internal::Inspect, Internal::MarshalSupport::WeakValue
Defined in:
lib/farce/weak_value.rb,
lib/farce/integrations/active_support/duplicable.rb

Overview

A weak value is similar to a WeakRef, but does not delegate method calls to the referenced object. If a weak value is created for a shareable object, it will also be shareable. If #freeze is called, the referenced object will be made shareable (unless it has been garbage collected).

Examples:

object = Object.new
weak   = Farce::WeakValue.new(object)
weak.value == object # => true
weak.alive?          # => true

# Shareability traversal
Ractor.shareable?(object) # => false
Ractor.shareable?(weak)   # => false

Ractor.make_shareable(weak)
Ractor.shareable?(weak)   # => true
Ractor.shareable?(object) # => true

# lets assume that the object has been garbage collected
object = nil
GC.start

weak.alive? # => false
weak.value # WeakRefError: Invalid Reference - probably recycled

ActiveSupport Integration collapse

Methods included from Abstract::Value

#blank?

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Abstract::Value

#unwrap

Constructor Details

#initialize(value) ⇒ WeakValue

Returns a new instance of WeakValue.

Parameters:

  • value (Object) —

    the object to be weakly referenced



101
102
103
104
105
106
107
108
109
# File 'lib/farce/weak_value.rb', line 101

def initialize(value)
  if Ractor.shareable?(value)
    @atom  = Strict::WeakAtom.new(value)
    @mutex = nil
  else
    @atom  = Unshared::WeakAtom.new(value)
    @mutex = Mutex.new
  end
end

Class Method Details

.new(value) ⇒ WeakValue

Returns a new weak value wrapping the given object.

Parameters:

  • value (Object) —

    the object to be weakly referenced

Returns:

  • (WeakValue) —

    a new weak value wrapping the given object

See Also:



89
# File 'lib/farce/weak_value.rb', line 89

def self.new(value) = value.nil? ? NIL_VALUE : super

Instance Method Details

#alive? ⇒ Boolean

Checks whether the referenced object has avoided garbage collection and has not been moved.

Returns:

  • (Boolean) —

    true if the weak value is still alive, false otherwise



113
114
115
116
117
# File 'lib/farce/weak_value.rb', line 113

def alive?
  !_value.nil?
rescue Ractor::MovedError
  false
end

#duplicable? ⇒ Boolean

Note:

This methods is only available if ActiveSupport has been loaded.

Returns true.

Returns:

  • (Boolean) —

    true



18
# File 'lib/farce/integrations/active_support/duplicable.rb', line 18

def duplicable? = true

#freeze ⇒ self

Freezes the weak value, making the referenced object shareable if it is still alive. Can be called after the value has been garbage collected or moved. Will raise however if the referenced object is still alive and cannot be made shareable.

Returns:

  • (self) —

    the frozen weak value



123
124
125
126
127
128
129
130
131
132
133
134
135
# File 'lib/farce/weak_value.rb', line 123

def freeze
  @mutex&.synchronize do
    return self if frozen?
    value = begin
      Ractor.make_shareable(_value)
    rescue Ractor::MovedError
      MOVED
    end
    @atom  = Strict::WeakAtom.new(value)
    @mutex = nil
  end
  super
end

#moved? ⇒ Boolean

Checks if the referenced object has been moved to another Ractor.

Returns:

  • (Boolean) —

    true if the referenced object has been moved, false otherwise



139
140
141
142
143
# File 'lib/farce/weak_value.rb', line 139

def moved?
  Ractor::MovedObject === _value
rescue Ractor::MovedError
  true
end

#ractor_shareable? ⇒ Boolean

Returns true if the referenced object is shareable by Ractor, false otherwise.

Returns:

  • (Boolean) —

    true if the referenced object is shareable by Ractor, false otherwise



146
147
148
149
150
151
# File 'lib/farce/weak_value.rb', line 146

def ractor_shareable?
  return false unless Ractor.shareable?(_value)
  freeze && true
rescue Ractor::MovedError
  freeze && true
end

#value ⇒ BasicObject

Retrieves the referenced object if it is still alive and has not been moved. Raises if it is no longer reachable.

Returns:

  • (BasicObject) —

    the referenced object if it is still alive and has not been moved

Raises:

  • (WeakRefError) —

    if the referenced object is no longer reachable or has been moved



157
158
159
160
161
162
163
# File 'lib/farce/weak_value.rb', line 157

def value
  value = _value
  raise WeakRefError, "Invalid Reference - probably recycled" if value.nil?
  value
rescue Ractor::MovedError
  raise WeakRefError, "Invalid Reference - referenced object has been moved"
end