docs: private List<DiffEntry> blockingCompareTrees(RevTree treeA, RevTree treeB) {
          if (cache == null) {
              return blockingCompareTreesUncached(treeA, treeB, TreeFilter.ALL);
          }
  
          final CacheableCompareTreesCall key = new CacheableCompareTreesCall(this, treeA, treeB);
          CompletableFuture<List<DiffEntry>> existingFuture = cache.getIfPresent(key);
          if (existingFuture != null) {
              final List<DiffEntry> existingDiffEntries = existingFuture.getNow(null);
              if (existingDiffEntries != null) {
                  // Cached already.
                  return existingDiffEntries;
              }
          }
  
          // Not cached yet. Acquire a lock so that we do not compare the same tree pairs simultaneously.
          final List<DiffEntry> newDiffEntries;
          final Lock lock = key.coarseGrainedLock();
          lock.lock();
          try {
              existingFuture = cache.getIfPresent(key);
              if (existingFuture != null) {
                  final List<DiffEntry> existingDiffEntries = existingFuture.getNow(null);
                  if (existingDiffEntries != null) {
                      // Other thread already put the entries to the cache before we acquire the lock.
                      return existingDiffEntries;
                  }
              }
  
              newDiffEntries = blockingCompareTreesUncached(treeA, treeB, TreeFilter.ALL);
              cache.put(key, newDiffEntries);
          } finally {
              lock.unlock();
          }
  
          logger.debug("Cache miss: {}", key);
          return newDiffEntries;
      }