docs: def traceroute_batch(input_list, results={}, method="udp", cmd_arguments=None,
                       delay_time=0.1, max_threads=100):
      """
      This is a parallel version of the traceroute primitive.
  
      :param input_list: the input is a list of domain names
      :param method: the packet type used for traceroute, UDP by default
      :param cmd_arguments: the list of arguments that need to be passed
                          to traceroute.
      :param delay_time: delay before starting each thread
      :param max_threads: maximum number of concurrent threads
      :return:
      """
      threads = []
      thread_error = False
      thread_wait_timeout = 200
      ind = 1
      total_item_count = len(input_list)
      for domain in input_list:
          wait_time = 0
          while threading.active_count() > max_threads:
              time.sleep(1)
              wait_time += 1
              if wait_time > thread_wait_timeout:
                  thread_error = True
                  break
  
          if thread_error:
              results["error"] = "Threads took too long to finish."
              break
  
          # add just a little bit of delay before starting the thread
          # to avoid overwhelming the connection.
          time.sleep(delay_time)
  
          log_prefix = "%d/%d: " % (ind, total_item_count)
          thread = threading.Thread(target=traceroute,
                                    args=(domain, method, cmd_arguments,
                                          results, log_prefix))
          ind += 1
          thread.setDaemon(1)
          thread_open_success = False
          retries = 0
          while not thread_open_success and retries < MAX_THREAD_START_RETRY:
              try:
                  thread.start()
                  threads.append(thread)
                  thread_open_success = True
              except:
                  retries += 1
                  time.sleep(THREAD_START_DELAY)
                  logging.error("%sThread start failed for %s, retrying... (%d/%d)" % (log_prefix, domain, retries, MAX_THREAD_START_RETRY))
  
          if retries == MAX_THREAD_START_RETRY:
              logging.error("%sCan't start a new thread for %s after %d retries." % (log_prefix, domain, retries))
  
      for thread in threads:
          thread.join(thread_wait_timeout)
  
      return results