views:

506

answers:

4

I've lived in the C++ world for years, and I'm just starting out with Ruby. I have a class that I would like to make a thread. In Ruby is it wrong to derive a class from Thread? The examples I see use the concept below.

Thread.new { <some block> }

Would it be wrong to do this?

class MyThread < Thread
  def initialize
  end

  def run
    <main loop>
  end
+4  A: 

That's perfectly fine, I've seen people do that before. Here's some example code from one of the Ruby mailing lists that runs when Thread.new is called:

class MyThread < Thread
  def initialize
    super("purple monkey dishwasher") {|str| puts "She said, '#{str}.'"}
  end
end

If you plan on calling Thread.fork or Thread.start to run your thread, you should be aware of this from the Ruby documentation those methods:

"Basically the same as Thread::new. However, if class Thread is subclassed, then calling start in that subclass will not invoke the subclass’s initialize method."

James Thompson
I guess the C++ programmer is coming out in me. Is it OK in Ruby to run the thread out of the constructor? Typically, that would never be done in C++.
nathan
I agree that it's a little bit odd, but it highlights the flexibility that Ruby gives you. Is this a good idea? It's a little odd, but it's certainly allowed by the class and language, and it's very readable. Others have pointed out that this isn't the standard thing to do, but I don't think it's the worst thing ever, and there might be an application for which this is perfect.
James Thompson
+1 For you answer James. You answered th asked question. Chris actually made me realize I was having a domain problem. Therefore the awarded answer goes to him.
nathan
+3  A: 

I think that this is really a question about domain modeling.

There would be nothing wrong with what you are doing if you want to extend / enhance the way that a thread behaves - for example to add debug or performance output but I don't think that's what you want.

You probably want to model some concept in your domain with active objects. In that case the standard Ruby approach is better because it allows you to achieve this without bending your domain model.

Inheritance really should only be used to model IS_A relationships. The standard ruby code for this neatly wraps up the solution.

To make your object active, have it capture the newly created thread in some method

Class MyClass

...


   def run
      while work_to_be_done do
         some_work
      end
   end

...

end


threads = []

# start creating active objects by creating an object and assigning
# a thread to each

threads << Thread.new { MyClass.new.run }

threads << Thread.new { MyOtherClass.new.run }

... do more stuff

# now we're done just wait for all objects to finish ....

threads.each { |t| t.join }


# ok, everyone is done, see starships on fire off the shoulder of etc
# time to die ...
Chris McCauley
Can you describe what the standard Ruby approach would be? Would it just be to pass a code block to the Thread object?
James Thompson
Yes - Thread.new { do_stuff } is the most common approach I've seen.
Greg Campbell
Updated my response with example of active object
Chris McCauley
Thanks Chris. After seeing your updated example, you were right. I was having trouble with which domain the class should exist. I ended up doing exactly what you have described here.
nathan
Glad to be of help. Let me know if you need more.
Chris McCauley
A: 

It's not really the ruby way, but it depends on what you are trying to accomplish with the thread.

First off, ruby 1.8 doesn't really have real threads, so they are only really useful for IO-bound things.

Generally in ruby you want something to perform an action in a thread rather than represent a thread, so it is easier to define an ordinary class that creates threads inside to handle the threading aspect.

Inheritance is an IS_A relationship

Ben Hughes
A: 

The Thread Ruby Documentation mentions "If the thread is subclassed" so it seems like it should be fine. Make sure if your overwriting initialize, you call super!

micmoo