/**
   * Waits for all workers to finish.
   *
   * @param cancel Flag to indicate whether workers should be cancelled before waiting for them to
   *     finish.
   */
  public void join(boolean cancel) {
    if (cancel) U.cancel(workers);

    // Record current interrupted status of calling thread.
    boolean interrupted = Thread.interrupted();

    try {
      U.join(workers, log);
    } finally {
      // Reset interrupted flag on calling thread.
      if (interrupted) Thread.currentThread().interrupt();
    }
  }
  /** {@inheritDoc} */
  @Override
  public void close() {
    closed = true;

    U.closeQuiet(srvSock);

    if (gcWorker != null) {
      U.cancel(gcWorker);

      // This method may be called from already interrupted thread.
      // Need to ensure cleaning on close.
      boolean interrupted = Thread.interrupted();

      try {
        U.join(gcWorker);
      } catch (IgniteInterruptedCheckedException e) {
        U.warn(log, "Interrupted when stopping GC worker.", e);
      } finally {
        if (interrupted) Thread.currentThread().interrupt();
      }
    }
  }