private void stopThread() { isDisposed = true; synchronized (documentsToCommit) { documentsToCommit.clear(); } cancel("Stop thread"); wakeUpQueue(); while (!threadFinished) { wakeUpQueue(); synchronized (documentsToCommit) { try { documentsToCommit.wait(10); } catch (InterruptedException ignored) { } } } }
public void disable(@NonNls Object reason) { // write action has just started, all commits are useless cancel(reason); myEnabled = false; log("Disabled", null, false, reason); }
@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); }