Thread: super should be first line or last line?


#1

While playing around with ruby threads I noticed that if you dont call
super when subclassing a thread you will get an initialization error.
So ok we throw a super in the initialize method and that clears things
up. Unfortunately if you put super as the first line in the initialize
method the rest of the initialize will not execute but the block which
is part of the initial thread creation gets initialized. However if
you put super as the last statement in the initialize method, the
whole initialize gets executed and then the block from the thread
creation gets executed. Does anyone else find this a bit funny? And
what is a good practice when subclassing thread… to put super first
or last statement in the initialize method? and is there any benefit
for either?


#2

2008/10/10 removed_email_address@domain.invalid removed_email_address@domain.invalid:

or last statement in the initialize method? and is there any benefit
for either?

Sorry, I haven’t a direct answer. Do you have a good reason to
subclass Thread? There’s probably a better way to achieve what
you want without subclassing.

Stefan


#3

On Oct 10, 9:43 am, Stefan L. removed_email_address@domain.invalid
wrote:

creation gets executed. Does anyone else find this a bit funny? And
what is a good practice when subclassing thread… to put super first
or last statement in the initialize method? and is there any benefit
for either?

Sorry, I haven’t a direct answer. Do you have a good reason to
subclass Thread? There’s probably a better way to achieve what
you want without subclassing.

Stefan

I’ve simply worked around the problem. I wanted the subclassed thread
simply to hold much more personal info( if you will ) related to that
particular’s threads behavior/action with in the environment its
running. There are many of threads going at any one time, and the info
within each one is both different and needed for each. By putting
super at the bottom of the initialize method i’ve solved the problem I
just thought it was a bit funny that if I put super at the top the
block associated with the creation of the thread gets called first and
then the rest of the initialize method runs. I guess I’ve just been
treated so kindly with java threads that doing things a bit
differently ( in terms of threads) through me for a loop. However I
still believe this is a bad design decision on behalf of thread
creation with ruby. Seemingly no matter what the initialize method
(imho) should be executed first … though as im writing this Im now
thinking there is reason to have both. I suppose there could be
reasons to have the block called first and then initialize the thread
just as well as there are reasons to have the thread be initialized
first and then call the corresponding block. Anyone have any opinions
on the subject?


#4

Hi –

On Fri, 10 Oct 2008, removed_email_address@domain.invalid wrote:

or last statement in the initialize method? and is there any benefit
for either?

I assume it’s just how Thread#initialize is defined. If it yields to
the block, and you call it, then it will yield to the block. It’s like
this:

class C
def initialize
yield
end
end

class D < C
def initialize
super
puts “Back from calling super”
end
end

D.new { puts “Inside block” }

Output:

Inside block
Back from calling super

It’s just executing commands in the order you issue them.

David


#5

removed_email_address@domain.invalid wrote:

or last statement in the initialize method? and is there any benefit
for either?

You can pass a block to super, and also yield within that block:

class MyThread < Thread
def initialize(*args)
puts “my init before super; Thread.current = #{Thread.current}”
super do
yield(*args)
puts “my init in super; Thread.current = #{Thread.current}”
end
puts “my init after super; Thread.current = #{Thread.current}”
end
end

th = MyThread.new do
puts “in block”
end

th.join

END

Output:

my init before super; Thread.current = #Thread:0xb7dd4700
in block
my init in super; Thread.current = #MyThread:0xb7cd4288
my init after super; Thread.current = #Thread:0xb7dd4700

(Note that the current thread is different for methods called within the
block.)


#6

Christopher Dancy wrote:

I’ve simply worked around the problem. I wanted the subclassed thread
simply to hold much more personal info( if you will ) related to that
particular’s threads behavior/action with in the environment its
running. There are many of threads going at any one time, and the info
within each one is both different and needed for each.

Another option to consider is using thread-local variables, rather than
instance variables in the thread object itself.

t = Thread.new {
Thread.current[:foo] = “bar”
}
t.join
puts t[:foo]


#7

2008/10/10 removed_email_address@domain.invalid removed_email_address@domain.invalid:

However I
still believe this is a bad design decision on behalf of thread
creation with ruby. … Anyone have any opinions
on the subject?

There’s nothing special going on. If you override a method in a
subclass, the original method is called if and only if you call super.
It would be a very bad design decision to deviate from this simple
and clear principal.

The task of the original Thread#initialize method is to spawn a new
thread and call the given block in the new thread. If you override the
#initialize method in your subclass and don’t call super, then no new
thread is created (who should do this and when ???). So it’s your
responsibility to invoke the original method when it’s appropriate for
your subclass. Since you obviously want to initialize some instance
variables before spawning the new thread, you should call super after
the initialization of your instance variables. If you want to do
something after spawning the new thread, you would put this code after
the call to super. As I said: there’s nothing special with class
Thread. It behaves as every other class in Ruby.

Regards,
Pit


#8

On 10.10.2008 15:02, removed_email_address@domain.invalid wrote:

While playing around with ruby threads I noticed that if you dont call
super when subclassing a thread you will get an initialization error.
So ok we throw a super in the initialize method and that clears things
up. Unfortunately if you put super as the first line in the initialize
method the rest of the initialize will not execute but the block which
is part of the initial thread creation gets initialized.

This is wrong.

irb(main):001:0> class T < Thread
irb(main):002:1> def initialize
irb(main):003:2> p self
irb(main):004:2> super
irb(main):005:2> p self
irb(main):006:2> end
irb(main):007:1> end

irb(main):009:0> T.new { sleep 1; p self }.join
#<T:0x7ff78b48 run>
#<T:0x7ff78b48 sleep>
main
=> #<T:0x7ff78b48 dead>
irb(main):010:0>

The code in the block gets executed. But the thread is started from
super so the thread is already running when the rest of initialize is
executed. One more reason why it is a bad idea to inherit Thread.

If you need to store information in the thread you can always use
Thread.current[:key] = value

However if
you put super as the last statement in the initialize method, the
whole initialize gets executed and then the block from the thread
creation gets executed. Does anyone else find this a bit funny? And
what is a good practice when subclassing thread… to put super first
or last statement in the initialize method? and is there any benefit
for either?

See above. If you need to do complex calculations you should rather
create a class that does the work and stores all necessary information.

Regards

robert


#9

removed_email_address@domain.invalid wrote:

or last statement in the initialize method? and is there any benefit
for either?

I’ll echo others’ concerns about why you’re doing this, but if the
initialize chain causes you headaches you could always redefine new for
your class:

class MyThread < Thread
def self.new(arg1, arg2)
super {
Thread.current[:arg1] = arg1
Thread.current[:arg2] = arg2
yield
}
}
}

It would probably be better put in a separate data structure that spins
up a Thread internally though.

  • Charlie

#10

On 11.10.2008 04:07, removed_email_address@domain.invalid wrote:

Thank you to everyone who has responded and for your insight. Coming
from a java threading background I simply assumed that creating a new
sub-classed thread would run the constructor and then the following
run method.

There is no run method in Ruby’s threads.

Thank you for the comments however they are much
appreciated and allowed me to see a different point of view.

You’re welcome.

Kind regards

robert


#11

On Oct 10, 6:19 pm, Charles Oliver N. removed_email_address@domain.invalid
wrote:

what is a good practice when subclassing thread… to put super first
Thread.current[:arg1] = arg1

  • Charlie
    Thank you to everyone who has responded and for your insight. Coming
    from a java threading background I simply assumed that creating a new
    sub-classed thread would run the constructor and then the following
    run method. Thank you for the comments however they are much
    appreciated and allowed me to see a different point of view.

Sincerely,
Chris Dancy