private void advance(Phase newPhase, boolean waitForOthers, boolean isSkip) {
      if (currentPhase == newPhase) {
        // normal case - still working on same phase
        counterForPhase.inc();
      } else if (newPhase.number < currentPhase.number) {
        throw new IllegalStateException(
          "Elements must be sorted with nodes first, then ways, then relations. Encountered " + newPhase + " after " +
            currentPhase);
      } else {
        // advance to next phase
        // but first, check if we skipped over some phases
        while (currentPhase.next() != newPhase) {
          advance(currentPhase.next(), true, true);
        }
        for (var action : finishActions.getOrDefault(currentPhase, List.of())) {
          action.runAndWrapException();
        }
        // increment the counter for the last element processed from the last phase, unless
        // the last phase was BEGIN, or we skipped over the last phase.
        if (counterForPhase != null && !skippedPhase) {
          counterForPhase.inc();
        }
        skippedPhase = isSkip;

        currentPhase = currentPhase.next();
        counterForPhase = counts.computeIfAbsent(currentPhase, p -> Counter.newMultiThreadCounter()).counterForThread();

        // don't let a worker move to next phase if other workers aren't even on that phase yet
        if (phaser.getPhase() < currentPhase.number - 1) {
          waitForAllToFinish(currentPhase.prev().prev());
        }
        phaser.arrive();
        if (waitForOthers) {
          waitForAllToFinish(currentPhase.prev());
        }
        workerStarted(currentPhase);

        // don't increment the counter since we want the count to go up after each element
        // was processed (not before).
      }
    }
Register {@code action} to run after this worker finished {@code phase}.
planetiler-core/src/main/java/com/onthegomap/planetiler/reader/osm/OsmPhaser.java