ruby - 针对 Ruby 规范强制 GC

标签 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 销毁我的主题对象。

提前致谢!!!

最佳答案

据我所知,这是不可能的。由特定的 Ruby 实现来决定是否以及何时实际销毁对象。由于垃圾收集是特定于实现的,因此不做任何保证。不幸的是,这意味着终结器可能永远不会被调用。但是,我认为规范也可以单独测试终结器。换句话说,当你手动触发GC时,你还不如手动触发finalizer并测试它的效果。

关于ruby - 针对 Ruby 规范强制 GC,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25334509/

相关文章:

ruby - 如何检查我安装的 Ruby 是否有调试符号?

ruby-on-rails - 如何在 Ruby on Rails 中获取月份名称?

ruby-on-rails - Rails to_xml 将选项添加到根节点

ruby - 是否可以在 Rspec 标签中包含条件逻辑

ruby - 在 Sinatra 模块化应用程序中设置 RSpec

ruby - 转换为 Ruby Enterprise 1.8.7 后内存大小增加

garbage-collection - 如何完成 lisp :struct containing a pointer?

ruby - Ruby 的数组如何。比较元素是否相等?

ruby-on-rails - rspec-rails:未定义方法 `true?' for true:TrueClass 更新到 3.0.0.beta2 版本后

objective-c - 双模 ARC/GC 和 Core Foundation 桥接