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 = SafeMonitor.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

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
# File 'lib/ref/abstract_reference_value_map.rb', line 30

def [](key)
  ref = @references[key]
  value = ref.object if ref
  value
end

#[]=(key, value) ⇒ Object

Add a key/value to the map.



37
38
39
40
41
42
43
44
45
46
47
48
49
50
# 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

#clearObject

Clear the map of all key/value pairs.



91
92
93
94
95
96
# 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) ⇒ Object

Remove the entry associated with the key from the map.



53
54
55
56
57
58
59
60
61
62
63
64
65
# 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

#eachObject

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



83
84
85
86
87
88
# 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

#inspectObject



105
106
107
108
109
110
111
# 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) ⇒ Object

Merge the values from another hash into this map.



99
100
101
102
103
# 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_aObject

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



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

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

#valuesObject

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



68
69
70
71
72
# File 'lib/ref/abstract_reference_value_map.rb', line 68

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