Class: Ref::AbstractReferenceValueMap

Inherits:
Object
  • Object
show all
Defined in:
lib/ref/abstract_reference_value_map.rb

Overview

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.

Direct Known Subclasses

SoftValueMap, WeakValueMap

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeAbstractReferenceValueMap

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.



21
22
23
24
25
26
# 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

Class Method Details

.reference_classObject

:nodoc:

Raises:

  • (NotImplementedError)


13
14
15
16
# File 'lib/ref/abstract_reference_value_map.rb', line 13

def reference_class #:nodoc:
  raise NotImplementedError.new("#{name} is an abstract class and cannot be instantiated") unless @reference_class
  @reference_class
end

.reference_class=(klass) ⇒ Object

:nodoc:



9
10
11
# File 'lib/ref/abstract_reference_value_map.rb', line 9

def reference_class=(klass) #:nodoc:
  @reference_class = klass
end

Instance Method Details

#[](key) ⇒ Object Also known as: get

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



30
31
32
33
34
35
36
# 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

#[]=(key, value) ⇒ Object Also known as: put

Add a key/value to the map.



41
42
43
44
45
46
47
48
49
50
51
52
53
54
# 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

#clearObject

Clear the map of all key/value pairs.



104
105
106
107
108
109
# File 'lib/ref/abstract_reference_value_map.rb', line 104

def clear
  @lock.synchronize do
    @references.clear
    @references_to_keys_map.clear
  end
end

#delete(key) ⇒ Object

Remove the entry associated with the key from the map.



59
60
61
62
63
64
65
66
67
68
69
70
71
# 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

#eachObject

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



96
97
98
99
100
101
# 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

#empty?Boolean

True if there are entries that exist in the map

Returns:

  • (Boolean)


140
141
142
143
144
145
146
# File 'lib/ref/abstract_reference_value_map.rb', line 140

def empty?
  @references.each do |_, ref|
    return false if ref.object
  end

  true
end

#inspectObject



148
149
150
151
152
153
154
# 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

#merge(other_hash, &block) ⇒ Object

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`.



116
117
118
119
120
121
# 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!(other_hash) ⇒ Object

Merge the values from another hash into this map.



124
125
126
127
128
# 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

#sizeObject Also known as: length

The number of entries in the map



131
132
133
134
135
# File 'lib/ref/abstract_reference_value_map.rb', line 131

def size
  @references.count do |_, ref|
    ref.object
  end
end

#to_aObject

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



81
82
83
84
85
# File 'lib/ref/abstract_reference_value_map.rb', line 81

def to_a
  array = []
  each{|k,v| array << [k, v]}
  array
end

#to_hObject

Returns a hash containing the names and values for the struct’s members.



88
89
90
91
92
# File 'lib/ref/abstract_reference_value_map.rb', line 88

def to_h
  hash = {}
  each{|k,v| hash[k] = v}
  hash
end

#valuesObject

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



74
75
76
77
78
# File 'lib/ref/abstract_reference_value_map.rb', line 74

def values
  vals = []
  each{|k,v| vals << v}
  vals
end