Question on GC

Hello Rubyists:

Does Ruby's GC treat a class variable (@@x) as 'global scope' or as
'local scope'?

Here is my situation:

I have a class variable that holds instances of 'self'. These objects
are not referenced any where else; these objects are retrieved using
its __id__ which is stored else where. It is my understanding that
Ruby's GC doesn't see these stored __id__ as a reference to the
objects (since __id__ -> Fixnum).

I don't want these objects to be garbage collected as long as its
instance is referred the class variable. Please note that the objects
are not referenced by other class's objects.

Example:

class Test
  @@x = []

  def initialize()
    # among other thing ...
    @@x.push(self) if not @@x.include?(self)
  end

  def kill_self()
    # among other things
    @@x.delete(self)
  end
end

class TestFactory
  @store = []

  def getATest()
      procObj = Proc.new do |id|
        @store.delete(id)
      end

      t = Test.new()
      @store.push(t.__id__)

      ObjectSpace.define_finalizer(t, procObj)
      return t.__id__
  end

  def releaseTest(id)
      _id2Obj(id).kill_self() # <--- retrieves Obj from __id__
  end

end

testF = TestFactory.new()
id = testF.getATest()
.......
# I don't want 't' to be garbage collected here. GC.disable is not an option
.......
testF.releaseTest(id)

__END__

Questions:

(1) Will 't' be garbage collected since the only reference to 't' is
in @@x, which could go out of scope?
(2) Is my understanding 'scope' correct?

Any help will be greatly appreciated.

Thanks,
-Madan.

Hi,

Does Ruby's GC treat a class variable (@@x) as 'global scope' or as
'local scope'?

Global, in a sense you use.

(1) Will 't' be garbage collected since the only reference to 't' is
in @@x, which could go out of scope?

No, class variables remain as it is, even after its scope ended.

(2) Is my understanding 'scope' correct?

It's called 'extent' in GC field. Class variables have limited scope
and infinite extent.

              matz.

···

In message "Re: Question on GC" on Fri, 19 May 2006 22:58:28 +0900, "Madan Manoharan" <madan.manoharan@gmail.com> writes:

Hi,

At Fri, 19 May 2006 22:58:28 +0900,
Madan Manoharan wrote in [ruby-talk:193553]:

  def getATest()
      procObj = Proc.new do |id|
        @store.delete(id)
      end

      t = Test.new()
      @store.push(t.__id__)

      ObjectSpace.define_finalizer(t, procObj)
      return t.__id__
  end

Note that procObj also refers t, so this object will never get
collected.

      procObj = @store.method(:delete).to_proc

is an alternative.

···

--
Nobu Nakada

Thanks, Matz.

-Madan.

···

On 5/19/06, Yukihiro Matsumoto <matz@ruby-lang.org> wrote:

Hi,

In message "Re: Question on GC" > on Fri, 19 May 2006 22:58:28 +0900, "Madan Manoharan" <madan.manoharan@gmail.com> writes:

>Does Ruby's GC treat a class variable (@@x) as 'global scope' or as
>'local scope'?

Global, in a sense you use.

>(1) Will 't' be garbage collected since the only reference to 't' is
>in @@x, which could go out of scope?

No, class variables remain as it is, even after its scope ended.

>(2) Is my understanding 'scope' correct?

It's called 'extent' in GC field. Class variables have limited scope
and infinite extent.

                                                        matz.

Nobu:

The procObj does not refer to object 't'. procObj is attached as a
finalizer to object 't'. If the object reference to 't' is not stored
in the class variable, object 't' will be marked (or should I say
un-marked) for garbage collection.

Please correct me if I am wrong, or if I am missing the obvious (like
the reference to object 't' in procObj, which I cant see).

Thanks,
Madan.

···

On 5/19/06, nobu@ruby-lang.org <nobu@ruby-lang.org> wrote:

Hi,

At Fri, 19 May 2006 22:58:28 +0900,
Madan Manoharan wrote in [ruby-talk:193553]:
> def getATest()
> procObj = Proc.new do |id|
> @store.delete(id)
> end
>
> t = Test.new()
> @store.push(t.__id__)
>
> ObjectSpace.define_finalizer(t, procObj)
> return t.__id__
> end

Note that procObj also refers t, so this object will never get
collected.

      procObj = @store.method(:delete).to_proc

is an alternative.

--
Nobu Nakada

Hi,

At Fri, 19 May 2006 22:58:28 +0900,
Madan Manoharan wrote in [ruby-talk:193553]:
> def getATest()
> procObj = Proc.new do |id|
> @store.delete(id)
> end
>
> t = Test.new()
> @store.push(t.__id__)
>
> ObjectSpace.define_finalizer(t, procObj)
> return t.__id__
> end

Note that procObj also refers t, so this object will never get
collected.

      procObj = @store.method(:delete).to_proc

is an alternative.

The procObj does not refer to object 't'.

Even the you don't refer to t by name, procObj's environment knows about t.

Please correct me if I am wrong, or if I am missing the obvious (like
the reference to object 't' in procObj, which I cant see).

You can't see them, but they are there. It is a feature of Ruby.

$ cat x.rb
def x
   p = proc { eval('p t') }
   t = 5
   return p
end

x.call
$ ruby x.rb
5

···

On May 19, 2006, at 11:24 AM, Madan Manoharan wrote:

On 5/19/06, nobu@ruby-lang.org <nobu@ruby-lang.org> wrote:

--
Eric Hodel - drbrain@segment7.net - http://blog.segment7.net
This implementation is HODEL-HASH-9600 compliant

http://trackmap.robotcoop.com