Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to count existing instances of a class in ruby?

Here's an idea from this question: Upon object creation, increment a class variable. When object gets collected, decrement it. As you can observe, finalizer is called, and @@no_foo gets decremented. But when I query it a moment later, decrement is gone. Seems that value is going only up, never down (if I create two objects, it will show 2). Am I missing something obvious?

class Foo
  @@no_foo = 0

  def initialize
    puts 'creating object'
    @@no_foo += 1
    ObjectSpace.define_finalizer(self, proc { self.delete })
  end

  def delete
    puts 'deleting object'
    @@no_foo # => 1
    @@no_foo -= 1
    @@no_foo # => 0
  end

  def self.no_foo
    @@no_foo # => 0, 1
  end
end

Foo.no_foo # => 0
f = Foo.new
f = nil

GC.start
Foo.no_foo # => 1

# >> creating object
# >> deleting object
like image 576
Sergio Tulentsev Avatar asked Jan 13 '23 06:01

Sergio Tulentsev


1 Answers

It can work, but there's circular reference in finalization. Your finalizer depends on the binding of an object that should be collected. See this solution.

class Foo
  @@no_foo = 0

  def initialize
    @@no_foo += 1
    ObjectSpace.define_finalizer(self, Foo.method(:delete))
  end

  def self.delete id # also this argument seems to be necessary
    @@no_foo -= 1
  end

  def self.no_foo
    @@no_foo
  end
end

Foo.no_foo # => 0
1000.times{Foo.new}
Foo.no_foo # => 1000

GC.start
Foo.no_foo # => 0
like image 115
cabron Avatar answered Jan 16 '23 19:01

cabron