@Override public void run() { threadFinished = false; while (!isDisposed) { try { boolean success = false; Document document = null; Project project = null; ProgressIndicator indicator = null; try { CommitTask task; synchronized (documentsToCommit) { if (!myEnabled || documentsToCommit.isEmpty()) { documentsToCommit.wait(); continue; } task = documentsToCommit.pullFirst(); document = task.document; indicator = task.indicator; project = task.project; log("Pulled", document, false, indicator); CommitStage commitStage = getCommitStage(document); Document[] uncommitted = null; if (commitStage != CommitStage.QUEUED_TO_COMMIT || project.isDisposed() || !ArrayUtil.contains( document, uncommitted = PsiDocumentManager.getInstance(project).getUncommittedDocuments())) { List<Document> documents = uncommitted == null ? null : Arrays.asList(uncommitted); log("Abandon and proceeding to next", document, false, commitStage, documents); continue; } if (indicator.isRunning()) { useIndicator(indicator); document.putUserData(COMMIT_PROGRESS, indicator); } else { success = true; // document has been marked as removed, e.g. by synchronous commit } } Runnable finishRunnable = null; if (!success && !indicator.isCanceled()) { try { finishRunnable = commit(document, project, null, indicator, false, task.reason); success = finishRunnable != null; log("DCT.commit returned", document, false, finishRunnable, indicator); } finally { document.putUserData(COMMIT_PROGRESS, null); } } synchronized (documentsToCommit) { if (indicator.isCanceled()) { success = false; } if (success) { assert !ApplicationManager.getApplication().isDispatchThread(); UIUtil.invokeLaterIfNeeded(finishRunnable); log( "Invoked later finishRunnable", document, false, success, finishRunnable, indicator); } } } catch (ProcessCanceledException e) { cancel(e); // leave queue unchanged log("PCE", document, false, e); success = false; } catch (InterruptedException e) { // app must be closing int i = 0; log("IE", document, false, e); cancel(e); } catch (Throwable e) { LOG.error(e); cancel(e); } synchronized (documentsToCommit) { if (!success && indicator.isRunning()) { // running means sync commit has not intervened // reset status for queue back successfully changeCommitStage( document, CommitStage.WAITING_FOR_PSI_APPLY, CommitStage.QUEUED_TO_COMMIT, false); changeCommitStage(document, CommitStage.COMMITTED, CommitStage.QUEUED_TO_COMMIT, false); doQueue(document, project, CommitStage.QUEUED_TO_COMMIT, "re-added on failure"); } } } catch (Throwable e) { e.printStackTrace(); // LOG.error(e); } } threadFinished = true; // ping the thread waiting for close wakeUpQueue(); log("Good bye", null, false); }
private void cancel(@NonNls Object reason) { log("Canceled", null, false, myProgressIndicator, "Reason: ", reason); useIndicator(null); }