class Opal::BuilderScheduler::Prefork

def prefork_reactor(rel_path, requires, autoloads, options)

def prefork_reactor(rel_path, requires, autoloads, options)
  prefork
  processed = []
  first = rel_path
  queue = requires.map { |i| [rel_path, i, autoloads, options] }
  awaiting = 0
  built = 0
  $stderr.print "\r\e[K" if $stderr.tty?
  loop do
    events, idles = @forks.get_events(queue.length)
    idles.each do |io|
      break if queue.empty?
      rel_path, req, autoloads, options = *queue.shift
      next if builder.already_processed.include?(req)
      awaiting += 1
      builder.already_processed << req
      io.send(:compile, rel_path, req, autoloads, options)
    end
    events.each do |io, type, *args|
      case type
      when :new_requires
        rel_path, requires, autoloads, options = *args
        requires.each do |i|
          queue << [rel_path, i, autoloads, options]
        end
      when :new_asset
        asset, = *args
        if !asset
          # Do nothing, we received a nil which is expected.
        else
          processed << asset
        end
        built += 1
        awaiting -= 1
      when :missing_require_exception
        rel_path, error = *args
        raise error, "A file required by #{rel_path.inspect} wasn't found.\n#{error.message}", error.backtrace
      when :exception
        error, = *args
        raise error
      when :close
        io.goodbye
      end
    end
    if $stderr.tty?
      percent = (100.0 * built / (awaiting + built)).round(1)
      str = format("[opal/builder] Building %<first>s... (%<percent>4.3g%%)\r", first: first, percent: percent)
      $stderr.print str
    end
    break if awaiting == 0 && queue.empty?
  end
  processed
ensure
  $stderr.print "\r\e[K\r" if $stderr.tty?
  @forks.close
  @forks.wait
end