Forum: Ruby Thread.current.parent and Thread.current.ancestors

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
unknown (Guest)
on 2007-02-16 08:56
(Received via mailing list)
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
Erik V. (Guest)
on 2007-02-16 11:06
(Received via mailing list)
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/
Erik V. (Guest)
on 2007-02-16 11:33
(Received via mailing list)
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
unknown (Guest)
on 2007-02-16 17:35
(Received via mailing list)
On Fri, 16 Feb 2007, Erik V. wrote:

> 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
This topic is locked and can not be replied to.