Hi all,
I'm trying to build a caching mechanism into a library I'm writing. I
want to do it using weakrefs. It will look something like this:

require 'weakref'

class Cache
  class << self
    @cache_hash = {}
    def insert(obj, id)
      @cache_hash[id] = WeakRef.new(obj)
    end

    def retrieve(id)
      o = @cache_hash[id]
      # If this object hasn't been GC'd yet
      if o.weakref_alive?
        # Return a strong ref to it.
        o.__getobj__
      else
        # Regenerate and return object
        # o = MyClass.fetch(id)
        insert(o, id)
        o
      end
    end
  end
end

Unfortunately, this doesn't work. The idea is that the cache always
returns strong-refs, so that the user doesn't have to worry about them
getting garbage-collected - to the user, they're just ordinary objects.
However, once they go outside the user's scope, the only reference to
them left is the weakref in the cache, and they can be garbage
collected. Then, if the user requests it again, it can be returned if
it's not GC'd yet, or regenerated and returned if it has.

It seems, though, that the WeakRef implementation is such that if you
refer to an object other than via its weakref, the weakref-ness is
destroyed and the object never gets GC'd. Can anyone explain why and/or
offer a way around this?

Tim Bates
-- 
tim / bates.id.au