强制GC用于Ruby的规范

时间:2014-08-15 21:30:27

标签: ruby rspec garbage-collection specifications

当我管理由外部C dll创建的很多对象时,我正在一个项目中工作。 现在,我从我的类Scope开始,它实现了一个模式来保存其他“可释放”对象的内存。因此,当Scope对象被销毁时,我需要为Scope对象将维护的每个引用调用release方法。 这是我的代码:

module ServiceBus

  class Scope
    def initialize
      @releaseables = []

      ObjectSpace.define_finalizer(self, self.class.finalize(@releaseables))
    end

    def self.finalize(releaseables)
      proc { releaseables.each { |obj| obj.release } }
    end

    def add_obj(obj)
      raise "#{self.class} only support releasbles objects" unless obj.respond_to?(:release)
      @releaseables << obj
    end
  end
end

和我的规格:

subject(:subject) { ServiceBus::Scope.new }

context "obj respons_to release" do
  let(:obj) do
    obj = double("ReleaseableObject")
    allow(obj).to receive(:release)

    obj
  end

  it "success" do
    subject.add_obj obj
  end

  it "call invoke for all added objects" do
    other_obj = double("ReleaseableObject")
    allow(other_obj).to receive(:release)

    subject.add_obj obj
    subject.add_obj other_obj

    subject = nil
    GC.start

    expect(other_obj).to have_received(:release)
    expect(other_obj).to have_received(:release)
  end
end

这是失败的,因为finalize永远不会在期望之前执行。 我应该如何强制GC销毁我的主题对象。

提前致谢!!!

1 个答案:

答案 0 :(得分:0)

据我所知,这是不可能的。由特定的Ruby实现决定是否以及何时实际销毁对象。由于垃圾收集是特定于实现的,因此不做任何保证。遗憾的是,这可能永远不会被称为终结者。但是,我认为规范也可以单独测试终结器。换句话说,当您手动触发GC时,您也可以手动触发终结器并测试其效果。