From 037544bdb53e51e22ed3aa4c47c1febd04dc41dc Mon Sep 17 00:00:00 2001 From: Andy Shipman Date: Thu, 25 Aug 2011 22:43:39 +0800 Subject: [PATCH] Add weakhash back in --- lib/sbdb/weakhash.rb | 59 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 lib/sbdb/weakhash.rb diff --git a/lib/sbdb/weakhash.rb b/lib/sbdb/weakhash.rb new file mode 100644 index 0000000..eb57ff0 --- /dev/null +++ b/lib/sbdb/weakhash.rb @@ -0,0 +1,59 @@ +module SBDB + # See http://eigenclass.org/hiki/deferred-finalizers-in-Ruby + # Not threadsafe. + class WeakHash + attr_reader :cache + 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| + @cache.delete @key_map.delete(key_id) if @key_map.has_key? key_id + end + end + + def []=(key, value) + case key + when Fixnum, Symbol, true, false + 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 + + ObjectSpace.define_finalizer(value, @reclaim_value) + ObjectSpace.define_finalizer(key, @reclaim_key) + value + end + + def [](key) + value_id = @cache[key] + return ObjectSpace._id2ref(value_id) unless value_id.nil? + nil + rescue RangeError + nil + end + + def each(&e) + @cache.each do |k, vid| + unless vid.nil? + obj = + begin + ObjectSpace._id2ref vid + rescue RangeError + next + end + yield k, obj + end + end + end + end +end