require 'thread' class ThreadEnsemble #--{{{ attr 'threads' def initialize @threads, @argv, @done, @running = [], [], Queue.new, false end def add_thread *a, &b @running ? raise : (@argv << [a, b]) end def killall (@threads - [Thread.current]).each{|t| t.kill rescue nil} if @running end def run @running = true begin @argv.each do |a, b| @threads << Thread.new(*a) do |*a| begin b[*a] ensure killall rescue nil if $! @done.push Thread.current end end end rescue killall raise ensure all_done end @threads.map{|t| t.value} end def all_done @threads.size.times{ @done.pop } end #--}}} end loop do te = ThreadEnsemble.new 1000.times do te.add_thread do raise end end begin te.run rescue running = te.threads.select{|t| t.status} abort running.inspect if running.size > 0 end end