Thread.current.parent and Thread.current.ancestors

can anyone see issues with this:

harp:~ > cat a.rb
class Thread
   class << self
     alias_method "__new__", "new"

     def new *a, &b
       parent = Thread.current

       __new__(*a) do |*a|
         Thread.current.parent = parent
         b.call *a
       end
     end

   end

   def parent
     self['parent']
   end

   def parent= parent
     self['parent'] = parent
   end

   def ancestors
     list = [t = self]
     while((t = t.parent))
       list << t
     end
     list
   end
end

Thread.new{ Thread.new{ Thread.new{ sleep 2; p Thread.current.ancestors } } }

STDIN.gets

harp:~ > ruby a.rb
[#<Thread:0xb75d2264 run>, #<Thread:0xb75d2354 dead>, #<Thread:0xb75d2444 dead>, #<Thread:0xb75df900 sleep>]

it's hard to wrap my head around, but even GC seems like it'd be fine - the
child, upon death, will allow the parent to be freed, and so on.

-a

···

--
we can deny everything, except that we have the possibility of being better.
simply reflect on that.
- the dalai lama

It doesn't work with Thread#start (==fork)...

Thread#start doesn't reuse Thread.new. Neither does
rb_thread_create(), which is used in e.g. TK.

All three methods (new, start/fork and rb_thread_create()) come
together in rb_thread_alloc(). That's the place where the
parent should be set. The problem is that you can't redefine
rb_thread_alloc() in Ruby... ;[

I really like this Thread.current.parent or Thread.parent.
There's at least one place where I really, really need it
myself... Something for Ruby 1.8.6?... ;]

gegroet,
Erik V. - http://www.erikveen.dds.nl/

Using new_with_parent (see below) has two advantages:

* By calling new_with_parent, you're saying: Yes, I know that
  parent doesn't work for all threads.

* Thread#parent doesn't return nil for "unpatched" threads,
  since it doesn't exist in the first place.

You can achieve the same by subclassing Thread.

Disadvantage:

* You can only ask for parents of your own threads. You can't
  ask for a parent of e.g. a DRb thread, since those aren't
  patched.

gegroet,
Erik V. - http://www.erikveen.dds.nl/

···

----------------------------------------------------------------

class Thread
   def self.new_with_parent(*args, &block)
     parent = Thread.current

     self.new do
       define_method :parent do
         parent
       end

       block.call(*args)
     end
   end
end

----------------------------------------------------------------

It doesn't work with Thread#start (==fork)...

Thread#start doesn't reuse Thread.new. Neither does
rb_thread_create(), which is used in e.g. TK.

All three methods (new, start/fork and rb_thread_create()) come
together in rb_thread_alloc(). That's the place where the
parent should be set. The problem is that you can't redefine
rb_thread_alloc() in Ruby... ;[

hrrrm. good point, this is the best i've come up with:

harp:~ > cat a.rb
class Thread
   class << self
     alias_method "__new__", "new"
     def new *a, &b
       child '__new__', *a, &b
     end
     alias_method "__start__", "start"
     def start *a, &b
       child '__start__', *a, &b
     end
   private
     def child as, *a, &b
       parent = Thread.current
       send(as, *a) do |*a|
         Thread.current.parent = parent
         b.call *a
       end
     end
   end
   def parent
     self['parent']
   end
   def parent= parent
     self['parent'] = parent
   end
   def ancestors
     return self['ancestors'] if self['ancestors']
     list = [t = self]
     while((t = t.parent))
       list << t
     end
     self['ancestors'] = list
   end
end

Thread.new{ Thread.new{ Thread.new{ sleep 0.42 and p [Thread.current, Thread.current.ancestors] } } }
Thread.start{ Thread.start{ Thread.start{ sleep 0.42 and p [Thread.current, Thread.current.ancestors] } } }

STDIN.gets

harp:~ > ruby a.rb
[#<Thread:0xb75cc0f8 run>, [#<Thread:0xb75cc0f8 run>, #<Thread:0xb75cc24c dead>, #<Thread:0xb75cc3a0 dead>, #<Thread:0xb75da748 sleep>]]
[#<Thread:0xb75cc508 run>, [#<Thread:0xb75cc508 run>, #<Thread:0xb75cc65c dead>, #<Thread:0xb75cc7b0 dead>, #<Thread:0xb75da748 sleep>]]

I really like this Thread.current.parent or Thread.parent.
There's at least one place where I really, really need it
myself... Something for Ruby 1.8.6?... ;]

RCR?

-a

···

On Fri, 16 Feb 2007, Erik Veenstra wrote:
--
we can deny everything, except that we have the possibility of being better.
simply reflect on that.
- the dalai lama