elk-reasoner/src/main/java/org/semanticweb/elk/reasoner/saturation/ClassExpressionSaturationFactory.java
private void updateFinishedCounters(ThisStatistics localStatistics)
			throws InterruptedException {
		int snapshotJobsProcessed = countJobsProcessedLower_.get();
		/*
		 * ensure that all contexts for processed jobs are marked as saturated
		 */
		for (;;) {
			int snapshotCountContextsSaturatedLower = countContextsSaturatedLower_
					.get();
			saturationState_
					.setContextsSaturated(snapshotCountContextsSaturatedLower);
			if (saturationState_
					.getContextSetSaturatedCount() < snapshotCountContextsSaturatedLower) {
				/*
				 * this means that some other worker also sets contexts as
				 * saturated, then it will mark the finished jobs instead
				 */
				return;
			}
			/*
			 * ensure that the counter for processed jobs is still up to date
			 */
			int updatedSnapshotJobsProcessed = countJobsProcessedLower_.get();
			if (updatedSnapshotJobsProcessed == snapshotJobsProcessed) {
				break;
			}
			/* else refresh counters */
			snapshotJobsProcessed = updatedSnapshotJobsProcessed;
		}
		/*
		 * ensure that all processed jobs are finished
		 */
		for (;;) {
			int snapshotJobsFinished = countJobsFinishedUpper_.get();
			if (snapshotJobsFinished >= snapshotJobsProcessed) {
				break;
			}
			/*
			 * update the finished context counter at least to the taken
			 * snapshot value and mark the corresponding number of jobs as
			 * processed
			 */
			if (!countJobsFinishedUpper_.compareAndSet(snapshotJobsFinished,
					snapshotJobsFinished + 1)) {
				/* retry */
				continue;
			}
			// else
			J nextJob = jobsInProgress_.poll();
			IndexedContextRoot root = nextJob.getInput();
			Context rootSaturation = saturationState_.getContext(root);
			if (rootSaturation.isInitialized()
					&& !rootSaturation.isSaturated()) {
				LOGGER_.error("{}: context for a finished job not saturated!",
						rootSaturation);
			}
			nextJob.setOutput(rootSaturation);

			LOGGER_.trace("{}: saturation finished", root);

			localStatistics.jobsProcessedNo++;
			listener_.notifyFinished(nextJob);// can be interrupted
		}

	}
private void updateFinishedCounters(ThisStatistics localStatistics)
			throws InterruptedException {
		int snapshotJobsProcessed = countJobsProcessedLower_.get();
		/*
		 * ensure that all contexts for processed jobs are marked as saturated
		 */
		for (;;) {
			int snapshotCountContextsSaturatedLower = countContextsSaturatedLower_
					.get();
			saturationState_
					.setContextsSaturated(snapshotCountContextsSaturatedLower);
			if (saturationState_
					.getContextSetSaturatedCount() < snapshotCountContextsSaturatedLower) {
				/*
				 * this means that some other worker also sets contexts as
				 * saturated, then it will mark the finished jobs instead
				 */
				return;
			}
			/*
			 * ensure that the counter for processed jobs is still up to date
			 */
			int updatedSnapshotJobsProcessed = countJobsProcessedLower_.get();
			if (updatedSnapshotJobsProcessed == snapshotJobsProcessed) {
				break;
			}
			/* else refresh counters */
			snapshotJobsProcessed = updatedSnapshotJobsProcessed;
		}
		/*
		 * ensure that all processed jobs are finished
		 */
		for (;;) {
			int snapshotJobsFinished = countJobsFinishedUpper_.get();
			if (snapshotJobsFinished >= snapshotJobsProcessed) {
				break;
			}
			/*
			 * update the finished context counter at least to the taken
			 * snapshot value and mark the corresponding number of jobs as
			 * processed
			 */
			if (!countJobsFinishedUpper_.compareAndSet(snapshotJobsFinished,
					snapshotJobsFinished + 1)) {
				/* retry */
				continue;
			}
			// else
			J nextJob = jobsInProgress_.poll();
			IndexedContextRoot root = nextJob.getInput();
			Context rootSaturation = saturationState_.getContext(root);
			if (rootSaturation.isInitialized()
					&& !rootSaturation.isSaturated()) {
				LOGGER_.error("{}: context for a finished job not saturated!",
						rootSaturation);
			}
			nextJob.setOutput(rootSaturation);

			LOGGER_.trace("{}: saturation finished", root);

			localStatistics.jobsProcessedNo++;
			listener_.notifyFinished(nextJob);// can be interrupted
		}

	}
Check if the counter for saturated contexts and processed jobs can be
increased and post-process the finished jobs

@throws InterruptedException