Class: WeakHash

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

Overview

This is a Hash where an association is removed as soon as either the key or the value are GCed.

When storing a value, the key is cloned and used in an internal hash (the cache) referetting to the object_id of the corresponding value.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(cache = Hash.new) ⇒ WeakHash

Returns a new instance of WeakHash.



16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# File 'lib/weak_hash.rb', line 16

def initialize( cache = Hash.new )
  @cache = cache
  @key_map = {}
  @rev_cache = Hash.new{|h,k| h[k] = {}}

  @reclaim_value = lambda do |value_id|
    if @rev_cache.has_key? value_id
      @rev_cache[value_id].each_key{|key| @cache.delete key}
      @rev_cache.delete value_id
    end
  end

  @reclaim_key = lambda do |key_id|
    if @key_map.has_key? key_id
      @cache.delete @key_map[key_id]
    end
  end
end

Instance Attribute Details

#cacheObject (readonly)

Returns the value of attribute cache.



14
15
16
# File 'lib/weak_hash.rb', line 14

def cache
  @cache
end

Instance Method Details

#[](key) ⇒ Object

retrieve object with the given key returns the object if present and it has not been garbage collected. Otherwise it returns nil.



38
39
40
41
42
43
44
# File 'lib/weak_hash.rb', line 38

def []( key )
  value_id = @cache[key]
  return ObjectSpace._id2ref(value_id) unless value_id.nil?
  nil
rescue RangeError
  nil
end

#[]=(key, value) ⇒ Object

“store” object into the weak hash using the given key a weak reference is stored so the object stays references as long as it isn’t garbage collected.



49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/weak_hash.rb', line 49

def []=( key, value )
  case key
  when Fixnum, Symbol, true, false, nil
    key2 = key
  else
    key2 = key.dup
  end

  @rev_cache[value.object_id][key2] = true
  @cache[key2] = value.object_id
  @key_map[key.object_id] = key2

  begin
    ObjectSpace.define_finalizer(value, @reclaim_value)
  rescue ArgumentError
    # Some objects will never be reclaimed by ObjectSpace, e.g. Fixnums
  end

  begin
    ObjectSpace.define_finalizer(key, @reclaim_key)
  rescue ArgumentError
    # Some objects will never be reclaimed by ObjectSpace, e.g. Fixnums
  end
end

#update(hash) ⇒ Object

an addition to Mauricio’s implementation, simple method that act’s like Hash#update method.



76
77
78
79
# File 'lib/weak_hash.rb', line 76

def update(hash)
  hash.each { |key, val| send(:[]=, key, val) }
  self
end