class Ref::AbstractReferenceValueMap

Abstract base class for WeakValueMap and SoftValueMap.

The classes behave similar to Hashes, but the values in the map are not strong references and can be reclaimed by the garbage collector at any time. When a value is reclaimed, the map entry will be removed.

Public Class Methods

new() click to toggle source

Create a new map. Values added to the map will be cleaned up by the garbage collector if there are no other reference except in the map.

# File lib/ref/abstract_reference_value_map.rb, line 21
def initialize
  @references = {}
  @references_to_keys_map = {}
  @lock = SafeMonitor.new
  @reference_cleanup = lambda{|object_id| remove_reference_to(object_id)}
end

Public Instance Methods

[](key) click to toggle source

Get a value from the map by key. If the value has been reclaimed by the garbage collector, this will return nil.

# File lib/ref/abstract_reference_value_map.rb, line 30
def [](key)
  ref = @references[key]
  value = ref.object if ref
  value
end
[]=(key, value) click to toggle source

Add a key/value to the map.

# File lib/ref/abstract_reference_value_map.rb, line 37
def []=(key, value)
  ObjectSpace.define_finalizer(value, @reference_cleanup)
  key = key.dup if key.is_a?(String)
  @lock.synchronize do
    @references[key] = self.class.reference_class.new(value)
    keys_for_id = @references_to_keys_map[value.__id__]
    unless keys_for_id
      keys_for_id = []
      @references_to_keys_map[value.__id__] = keys_for_id
    end
    keys_for_id << key
  end
  value
end
clear() click to toggle source

Clear the map of all key/value pairs.

# File lib/ref/abstract_reference_value_map.rb, line 91
def clear
  @lock.synchronize do
    @references.clear
    @references_to_keys_map.clear
  end
end
delete(key) click to toggle source

Remove the entry associated with the key from the map.

# File lib/ref/abstract_reference_value_map.rb, line 53
def delete(key)
  ref = @references.delete(key)
  if ref
    keys_to_id = @references_to_keys_map[ref.referenced_object_id]
    if keys_to_id
      keys_to_id.delete(key)
      @references_to_keys_map.delete(ref.referenced_object_id) if keys_to_id.empty?
    end
    ref.object
  else
    nil
  end
end
each() { |key, value| ... } click to toggle source

Iterate through all the key/value pairs in the map that have not been reclaimed by the garbage collector.

# File lib/ref/abstract_reference_value_map.rb, line 83
def each
  @references.each do |key, ref|
    value = ref.object
    yield(key, value) if value
  end
end
inspect() click to toggle source
# File lib/ref/abstract_reference_value_map.rb, line 105
def inspect
  live_entries = {}
  each do |key, value|
    live_entries[key] = value
  end
  live_entries.inspect
end
merge!(other_hash) click to toggle source

Merge the values from another hash into this map.

# File lib/ref/abstract_reference_value_map.rb, line 99
def merge!(other_hash)
  other_hash.each do |key, value|
    self[key] = value
  end
end
to_a() click to toggle source

Turn the map into an arry of [key, value] entries

# File lib/ref/abstract_reference_value_map.rb, line 75
def to_a
  array = []
  each{|k,v| array << [k, v]}
  array
end
values() click to toggle source

Get the list of all values that have not yet been garbage collected.

# File lib/ref/abstract_reference_value_map.rb, line 68
def values
  vals = []
  each{|k,v| vals << v}
  vals
end

Private Instance Methods

remove_reference_to(object_id) click to toggle source
# File lib/ref/abstract_reference_value_map.rb, line 115
def remove_reference_to(object_id)
  @lock.synchronize do
    keys = @references_to_keys_map[object_id]
    if keys
      keys.each do |key|
        @references.delete(key)
      end
      @references_to_keys_map.delete(object_id)
    end
  end
end