class Open4::ThreadEnsemble
def add_thread *a, &b
def add_thread *a, &b @running ? raise : (@argv << [a, b]) end
def all_done
def all_done @threads.size.times{ @done.pop } end
def initialize cid
def initialize cid @cid, @threads, @argv, @done, @running = cid, [], [], Queue.new, false @killed = false end
def killall
take down process more nicely
def killall c = Thread.critical return nil if @killed Thread.critical = true (@threads - [Thread.current]).each{|t| t.kill rescue nil} @killed = true ensure Thread.critical = c end
def run
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