Class: Ref::AbstractReferenceKeyMap

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

Overview

Abstract base class for WeakKeyMap and SoftKeyMap.

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

Direct Known Subclasses

SoftKeyMap, WeakKeyMap

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeAbstractReferenceKeyMap

Create a new map. Values added to the hash 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_key_map.rb', line 21

def initialize
  @values = {}
  @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_key_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_key_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
# File 'lib/ref/abstract_reference_key_map.rb', line 30

def [](key)
  @lock.synchronize do
    rkey = ref_key(key)
    @values[rkey] if rkey
  end
end

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

Add a key/value to the map.



40
41
42
43
44
45
46
# File 'lib/ref/abstract_reference_key_map.rb', line 40

def []=(key, value)
  ObjectSpace.define_finalizer(key, @reference_cleanup)
  @lock.synchronize do
    @references_to_keys_map[key.__id__] = self.class.reference_class.new(key)
    @values[key.__id__] = value
  end
end

#clearObject

Clear the map of all key/value pairs.



92
93
94
95
96
97
# File 'lib/ref/abstract_reference_key_map.rb', line 92

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

#delete(key) ⇒ Object

Remove the value associated with the key from the map.



51
52
53
54
55
56
57
58
59
60
61
# File 'lib/ref/abstract_reference_key_map.rb', line 51

def delete(key)
  @lock.synchronize do
    rkey = ref_key(key)
    if rkey
      @references_to_keys_map.delete(rkey)
      @values.delete(rkey)
    else
      nil
    end
  end
end

#eachObject

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



84
85
86
87
88
89
# File 'lib/ref/abstract_reference_key_map.rb', line 84

def each
  @references_to_keys_map.each do |rkey, ref|
    key = ref.object
    yield(key, @values[rkey]) if key
  end
end

#empty?Boolean

True if there are entries that exist in the map

Returns:

  • (Boolean)


128
129
130
131
132
133
# File 'lib/ref/abstract_reference_key_map.rb', line 128

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

#inspectObject



135
136
137
138
139
140
141
# File 'lib/ref/abstract_reference_key_map.rb', line 135

def inspect
  live_entries = {}
  each do |key, value|
    live_entries[key] = value
  end
  live_entries.inspect
end

#keysObject

Get an array of keys that have not yet been garbage collected.



64
65
66
# File 'lib/ref/abstract_reference_key_map.rb', line 64

def keys
  @values.keys.collect{|rkey| @references_to_keys_map[rkey].object}.compact
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`.



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

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.



112
113
114
115
116
# File 'lib/ref/abstract_reference_key_map.rb', line 112

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



119
120
121
122
123
# File 'lib/ref/abstract_reference_key_map.rb', line 119

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

#to_aObject

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



69
70
71
72
73
# File 'lib/ref/abstract_reference_key_map.rb', line 69

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.



76
77
78
79
80
# File 'lib/ref/abstract_reference_key_map.rb', line 76

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