红宝石对象缓存

5
我有许多带有唯一ID的Ruby对象,目前我正在使用Hash进行缓存。当对象被分配一个ID时,它就进入了Hash。缓存是完整的,也就是说,Ruby范围内存在ID的每个对象都应该在缓存中。
然而,我无法找到一种方法来从缓存中删除对象,一旦它们从所有其他作用域中消失。这当然是因为包含在缓存中的对象不会被垃圾回收。
有没有解决这个问题的方法?文档WeakRef提供了一个WeakHash类,但它似乎不适合实际使用,尽管它非常接近我认为我需要的项目。

1
为什么这不是实际可行的呢? - Marc-André Lafortune
1
WeakRef 是你所需要的。 - Linuxios
1个回答

3

类似 WeakHash 这样的东西可以实现它。以下是一个更完整的实现,可以处理 Fixnums、Symbols 和 Floats(如果您将其他不可变类型添加到列表中,则也可以):

class WeakHash < Hash
  def []=(k, v)
    if(![Fixnum, Symbol, Float].include? k.class)
      k = WeakRef.new(k)
    end
    if(![Fixnum, Symbol, Float].include? v.class)
      v = WeakRef.new(v)
    end
    super k,v
  end
end

这与WeakRef文档中给出的示例非常相似,但这里没有内存泄漏吗?存储在此哈希表中的对象实际上是垃圾收集的,但weakhash.count从未减少。这是一件坏事吗? - Vortico
@Vortico:不是内存泄漏,只是计数泄漏。我会编辑并修复它。 - Linuxios
你可以使用 unless 代替 if ! - AJcodez
1
当一个值在缓存中时,如何查找它?你不能简单地使用[],因为它会尝试查找原始值而不是WeakHash实例... ??? - Henrik Lindberg
@HenrikLindberg:你说得没错,我也不太确定该怎么解决。WeakRef文档说它们可以像引用的对象一样使用,但显然这并不包括哈希码。你可能需要子类化WeakRef与一些新类(如WeakKey)一起,还要覆盖eql?equal?hash方法(我已经很久没写Ruby了)以使用被引用对象的实现。 - Linuxios

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接