Mauricio Fernandez wrote: > class WeakCache > attr_reader :cache > def initialize( cache = Hash.new ) > @cache = cache > end > > def []( key ) > value_id = @cache[key] > return ObjectSpace._id2ref(value_id) unless value_id.nil? > nil > end > > def make_lambda(key) > lambda{|value| @cache.delete(key) } > end > > def []=( key, value ) > ObjectSpace.define_finalizer(value, make_lambda(key)) > @cache[key] = value.object_id > end > end > > RUBY_VERSION # => "1.8.4" > RUBY_RELEASE_DATE # => "2005-12-24" > c = WeakCache.new > puts c.cache.size > 100000.times{|i| c[i] = i.to_s} > GC.start > puts c.cache.size > __END__ > # >> 0 > # >> 3 > > > > That is very inefficient though, you want something more like > > > class WeakCache > attr_reader :cache > def initialize( cache = Hash.new ) > @cache = cache > @rev_cache = {} > @reclaim_method = method(:reclaim_value) > end > > def []( key ) > value_id = @cache[key] > return ObjectSpace._id2ref(value_id) unless value_id.nil? > nil > end > > def reclaim_value(value_id) > @cache.delete @rev_cache[value_id] > @rev_cache.delete value_id > end > > def []=( key, value ) > @rev_cache[value.object_id] = key > @cache[key] = value.object_id > ObjectSpace.define_finalizer(value, @reclaim_method) > end > end > > RUBY_VERSION # => "1.8.4" > RUBY_RELEASE_DATE # => "2005-12-24" > c = WeakCache.new > puts c.cache.size > 100000.times{|i| c[i] = i.to_s} > GC.start > puts c.cache.size > __END__ > # >> 0 > # >> 4 > > I like your technique, but suppose the same value is stored for more than one key in a WeakCache? When the value is finalized, only the last key will be removed from the cache. I think it might be better to let the reverse cache hold more than one key per value.