On Wed, Jan 25, 2006 at 12:58:04AM +0900, Jeffrey Schwab wrote: > > 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 [...] > 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. You're very right, I should have written something like class WeakCache attr_reader :cache def initialize( cache = Hash.new ) @cache = cache @rev_cache = Hash.new{|h,k| h[k] = {}} @reclaim_lambda = 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 end def []( key ) value_id = @cache[key] return ObjectSpace._id2ref(value_id) unless value_id.nil? nil end def []=( key, value ) @rev_cache[value.object_id][key] = true @cache[key] = value.object_id ObjectSpace.define_finalizer(value, @reclaim_lambda) end end puts "=" * 20 c = WeakCache.new puts c.cache.size 100000.times{|i| c[i] = (i % 1000).to_s} GC.start puts c.cache.size puts "=" * 20 # >> ==================== # >> 0 # >> 3 # >> ==================== (not thread-safe yet though) -- Mauricio Fernandez