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
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 = Monitor.new @reference_cleanup = lambda{|object_id| remove_reference_to(object_id)} end
Public Instance Methods
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) @lock.synchronize do ref = @references[key] value = ref.object if ref value end end
Add a key/value to the map.
# File lib/ref/abstract_reference_value_map.rb, line 41 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 the map of all key/value pairs.
# File lib/ref/abstract_reference_value_map.rb, line 104 def clear @lock.synchronize do @references.clear @references_to_keys_map.clear end end
Remove the entry associated with the key from the map.
# File lib/ref/abstract_reference_value_map.rb, line 59 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
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 96 def each @references.each do |key, ref| value = ref.object yield(key, value) if value end end
True if there are entries that exist in the map
# File lib/ref/abstract_reference_value_map.rb, line 140 def empty? @references.each do |_, ref| return false if ref.object end true end
# File lib/ref/abstract_reference_value_map.rb, line 148 def inspect live_entries = {} each do |key, value| live_entries[key] = value end live_entries.inspect end
Returns a new struct containing the contents of `other` and the contents of `self`. If no block is specified, the value for entries with duplicate keys will be that of `other`. Otherwise the value for each duplicate key is determined by calling the block with the key, its value in `self` and its value in `other`.
# File lib/ref/abstract_reference_value_map.rb, line 116 def merge(other_hash, &block) to_h.merge(other_hash, &block).reduce(self.class.new) do |map, pair| map[pair.first] = pair.last map end end
Merge the values from another hash into this map.
# File lib/ref/abstract_reference_value_map.rb, line 124 def merge!(other_hash) @lock.synchronize do other_hash.each { |key, value| self[key] = value } end end
The number of entries in the map
# File lib/ref/abstract_reference_value_map.rb, line 131 def size @references.count do |_, ref| ref.object end end
Turn the map into an arry of [key, value] entries
# File lib/ref/abstract_reference_value_map.rb, line 81 def to_a array = [] each{|k,v| array << [k, v]} array end
Returns a hash containing the names and values for the struct’s members.
# File lib/ref/abstract_reference_value_map.rb, line 88 def to_h hash = {} each{|k,v| hash[k] = v} hash end
Get the list of all values that have not yet been garbage collected.
# File lib/ref/abstract_reference_value_map.rb, line 74 def values vals = [] each{|k,v| vals << v} vals end
Private Instance Methods
# File lib/ref/abstract_reference_value_map.rb, line 158 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