require 'open-uri' min = ARGV[0].to_i max = ARGV[1].to_i require 'thread' class PooledRunner def initialize(klass, howmany, args, debug = false) @mutex = Mutex.new @pool = [] @handleravail = ConditionVariable.new howmany.times { @pool << klass.new(*args) } @threads = {} puts "Handler pool: #{@pool.inspect}" if debug end def run(debug = false) ref = [] handler = nil @mutex.synchronize do info = false if @pool.size == 0 @handleravail.wait @mutex info = true if debug end handler = @pool.shift puts "Got handler #{handler} after getting blocked." if info @threads[handler] = ref # hack cause want this # inside synchronize; perhaps not needed end ref << Thread.new do begin yield handler ensure @mutex.synchronize do @pool << handler @threads.delete handler @handleravail.signal end end end ref[0] end def wait_for_all @threads.each do |handler, thread| thread[0].join end end def close_handlers wait_for_all @pool.each { |x| x.close } end def num_tasks @threads.size end end if min >= max puts "give 2 nums" exit end class Getter def get(i) puts "Downloading #{i}" begin open("http://blade.nagaokaut.ac.jp/ruby/ruby-talk/#{i}") do |is| File.open("#{i}", "w") do |os| while data = is.read os.write data break if is.eof? end end end rescue end end def close end end runner = PooledRunner.new(Getter, 40, [], false) (min..max).each do |i| runner.run do |handler| handler.get i end end runner.wait_for_all runner.close_handlers