void submitOrScheduleCoalesced(@NotNull List<?> coalesceEquality) {
      synchronized (ourTasksByEquality) {
        if (isDone()) return;

        Submission<?> current = ourTasksByEquality.putIfAbsent(coalesceEquality, this);
        if (current == null) {
          transferToBgThread();
        }
        else {
          if (!current.getComputationOrigin().equals(getComputationOrigin())) {
            //RC: Sort of fool-proofing: sometimes it _could_ be OK to invoke 2 ReadActions with different .computable
            //    from different places in code, but with same .coalesceBy -- but it is much more likely an error.
            //    Hence, we prefer to prohibit it completely:
            reportCoalescingConflict(current);
          }
          if (current.myReplacement != null) {
            current.myReplacement.cancel();
            assert current == ourTasksByEquality.get(coalesceEquality);
          }
          current.myReplacement = this;
          current.cancel();
        }
      }
    }
void submitOrScheduleCoalesced(@NotNull List<?> coalesceEquality)