philipjkim
philipjkim

Reputation: 4139

Can EventMachine recognize all threads are completed?

I'm an EM newbie and writing two codes to compare synchronous and asynchronous IO. I'm using Ruby 1.8.7.

The example for sync IO is:

def pause_then_print(str)
  sleep 2
  puts str
end

5.times { |i| pause_then_print(i) }

puts "Done"

This works as expected, taking 10+ seconds until termination.

On the other hand, the example for async IO is:

require 'rubygems'
require 'eventmachine'

def pause_then_print(str)
  Thread.new do
    EM.run do
      sleep 2
      puts str
    end
  end
end

EventMachine.run do
  EM.add_timer(2.5) do
    puts "Done"
    EM.stop_event_loop
  end
  EM.defer(proc do
    5.times { |i| pause_then_print(i) }
  end)
end

5 numbers are shown in 2.x seconds.

Now I explicitly wrote code that EM event loop to be stopped after 2.5 seconds. But what I want is that the program terminates right after printing out 5 numbers. For doing that, I think EventMachine should recognize all 5 threads are done, and then stop the event loop.

How can I do that? Also, please correct the async IO example if it can be more natural and expressive.

Thanks in advance.

Upvotes: 0

Views: 177

Answers (1)

dj2
dj2

Reputation: 9598

A few things about your Async code. EM.defer schedules the code to execute on a thread. You're then creating more threads. There isn't much point to doing that when you could just use EM.defer in your creation loop. This has the added benefit that EM will service the threads from it's internal threadpool which should be a bit faster as there is no thread creation overhead. (Just note, the EM threadpool has, I believe, 20 threads in it so you want to stay below that number). Something like the following should work (although I haven't tested it)

require 'rubygems'
require 'eventmachine'

def pause_then_print(str)
  sleep 2
  puts str
end

EventMachine.run do
  EM.add_timer(2.5) do
    puts "Done"
    EM.stop_event_loop
  end
  5.times do |i|
    EM.defer { pause_then_print(i) }
  end
end

In terms of detecting when the work is done, you can have EM.defer execute a callback when its operation is complete. So, you could have a little bit of code in there that adds the callback when i == 4, or something similar. See the EM docs for how to add the callback: EM.defer

Upvotes: 1

Related Questions