private void doComplete(Throwable throwable) {
    ApplierCompleter<T> a = this;
    ApplierCompleter<T> child = a;
    while (true) {
      // update parent.throwable in a thread safe way
      Throwable oldThrowable;
      Throwable newThrowable;
      do {
        oldThrowable = a.throwable;
        newThrowable = moreImportant(oldThrowable, throwable);
      } while (oldThrowable != newThrowable && !throwableUpdater.compareAndSet(a, oldThrowable, newThrowable));
      throwable = newThrowable;
      if (a.getPendingCount() == 0) {
        // currently avoid using onExceptionalCompletion since it leaks exceptions via ForkJoinTask.exceptionTable
        a.onCompletion(child);
        //a.onExceptionalCompletion(throwable, child);
        child = a;
        //noinspection unchecked
        a = (ApplierCompleter<T>)a.getCompleter();
        if (a == null) {
          // currently avoid using completeExceptionally since it leaks exceptions via ForkJoinTask.exceptionTable
          child.quietlyComplete();
          break;
        }
      }
      else if (a.decrementPendingCountUnlessZero() != 0) {
        break;
      }
    }
  }
private void doComplete(Throwable throwable)