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 = 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_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

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

def [](key)
  rkey = ref_key(key)
  @values[rkey] if rkey
end

#[]=(key, value) ⇒ Object

Add a key/value to the map.



36
37
38
39
40
41
42
# File 'lib/ref/abstract_reference_key_map.rb', line 36

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.



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

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.



45
46
47
48
49
50
51
52
53
# File 'lib/ref/abstract_reference_key_map.rb', line 45

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

#eachObject

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



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

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

#inspectObject



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

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.



56
57
58
# File 'lib/ref/abstract_reference_key_map.rb', line 56

def keys
  @values.keys.collect{|rkey| @references_to_keys_map[rkey].object}.compact
end

#merge!(other_hash) ⇒ Object

Merge the values from another hash into this map.



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

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.



61
62
63
64
65
# File 'lib/ref/abstract_reference_key_map.rb', line 61

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