2008/9/17 ara.t.howard <ara.t.howard / gmail.com>:
>
> On Sep 17, 2008, at 8:49 AM, Brian Candler wrote:
>
>> Your version only works because the threads are dying after 2 seconds.
>> Change
>>
>>  def make_thread
>>   Thread.new { sleep 2 }
>>  end
>>
>> to
>>
>>  def make_thread
>>   Thread.new { sleep 10000 }
>>  end
>>
>> and run it again.

Good point!

> but that it expected?  you have a Foo which referes to a Thread which has
> not died that is itself referred to by the global Thread.list

Yeah, but there is no reference back to the Foos so they could be collected.

If you change the code to

def make_thread
  Thread.new { loop { sleep 2 } }
end

...

1000.times {
  Foo.new.bar = "x" * rand(100) # make_thread
}

Then Foo instances are quickly removed although 1 is still referenced.
 The only explanation I have ATM is that the thread stack might be
copied somehow and thus keep the ref alive.  Interesting enough ruby19
behaves much differently: the count goes down to 0 instead of 1.  But
with the old version (i.e. Foo.new.bar = make_thread) I get thread
creation errors.  With some changing the number actually goes down to
0:

17:43:31 Temp$ cat gc.rb

def make_thread
  Thread.new { loop { sleep 2 } }
  # Thread.new { loop { Array.new(1_000_000); sleep 0.1 } }
end

class Module
  def count
    c = 0
    ObjectSpace.each_object(self) { c += 1 }
    c
  end
end

Foo = Struct.new :bar

10.times {
  # Foo.new.bar = "x" * rand(100)
  Foo.new.bar = make_thread
}

puts "Threads created"

# use memory
Thread.new { loop { Array.new(1_000_000); sleep 0.1 } }

loop do
  puts Foo.count
  GC.start
  sleep 1
end

17:43:37 Temp$ ruby19 --version
ruby 1.9.0 (2008-03-01 revision 15664) [i386-cygwin]
17:43:48 Temp$ ruby19 gc.rb
Threads created
10
0
0
0
0
0
0
0
0
0
17:44:01 Temp$

Kind regards

robert

-- 
use.inject do |as, often| as.you_can - without end