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