diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/index/VcsLogPersistentIndex.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/index/VcsLogPersistentIndex.java index 6ffa2c34ab5f..b613ca1898b2 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/index/VcsLogPersistentIndex.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/index/VcsLogPersistentIndex.java @@ -19,7 +19,10 @@ import com.intellij.openapi.Disposable; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.progress.*; +import com.intellij.openapi.progress.PerformInBackgroundOption; +import com.intellij.openapi.progress.ProcessCanceledException; +import com.intellij.openapi.progress.ProgressIndicator; +import com.intellij.openapi.progress.Task; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.Disposer; @@ -36,6 +39,7 @@ import com.intellij.util.io.*; import com.intellij.vcs.log.*; import com.intellij.vcs.log.data.*; import com.intellij.vcs.log.impl.FatalErrorHandler; +import com.intellij.vcs.log.impl.HeavyAwareExecutor; import com.intellij.vcs.log.ui.filter.VcsLogTextFilterImpl; import com.intellij.vcs.log.util.PersistentSet; import com.intellij.vcs.log.util.PersistentSetImpl; @@ -491,6 +495,7 @@ public class VcsLogPersistentIndex implements VcsLogIndex, Disposable { ApplicationManager.getApplication().invokeLater(() -> { Task.Backgroundable task = new Task.Backgroundable(VcsLogPersistentIndex.this.myProject, "Indexing Commit Data", true, PerformInBackgroundOption.ALWAYS_BACKGROUND) { + @Override public void run(@NotNull ProgressIndicator indicator) { IndexingRequest request; @@ -510,7 +515,7 @@ public class VcsLogPersistentIndex implements VcsLogIndex, Disposable { taskCompleted(null); } }; - ProgressManager.getInstance().runProcessWithProgressAsynchronously(task, indicator); + HeavyAwareExecutor.executeOutOfHeavyProcess(task, indicator); }); return indicator; } diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/HeavyAwareExecutor.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/HeavyAwareExecutor.java index db7974c851a0..8e2ed9270a90 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/HeavyAwareExecutor.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/HeavyAwareExecutor.java @@ -16,13 +16,19 @@ package com.intellij.vcs.log.impl; import com.intellij.concurrency.JobScheduler; +import com.intellij.openapi.Disposable; +import com.intellij.openapi.progress.ProgressIndicator; +import com.intellij.openapi.progress.ProgressManager; +import com.intellij.openapi.progress.Task; +import com.intellij.openapi.progress.impl.CoreProgressManager; +import com.intellij.openapi.util.Disposer; import com.intellij.util.io.storage.HeavyProcessLatch; import org.jetbrains.annotations.NotNull; import java.util.concurrent.TimeUnit; -class HeavyAwareExecutor { - static void executeOutOfHeavyProcessLater(@NotNull Runnable command, int delayMs) { +public class HeavyAwareExecutor { + public static void executeOutOfHeavyProcessLater(@NotNull Runnable command, int delayMs) { HeavyProcessLatch.INSTANCE.executeOutOfHeavyProcess(() -> JobScheduler.getScheduler().schedule(() -> { if (HeavyProcessLatch.INSTANCE.isRunning()) { executeOutOfHeavyProcessLater(command, delayMs); @@ -32,4 +38,35 @@ class HeavyAwareExecutor { } }, delayMs, TimeUnit.MILLISECONDS)); } + + public static void executeOutOfHeavyProcess(@NotNull Task.Backgroundable task, @NotNull ProgressIndicator indicator) { + HeavyProcessLatch.INSTANCE.executeOutOfHeavyProcess(() -> { + if (HeavyProcessLatch.INSTANCE.isRunning()) { + executeOutOfHeavyProcess(task, indicator); + } + else { + Disposable disposable = Disposer.newDisposable(); + ((CoreProgressManager)ProgressManager.getInstance()).runProcessWithProgressAsynchronously(task, indicator, + () -> Disposer.dispose(disposable)); + HeavyProcessLatch.INSTANCE.addListener(new CancellingOnHeavyProcessListener(indicator), disposable); + } + }); + } + + private static class CancellingOnHeavyProcessListener implements HeavyProcessLatch.HeavyProcessListener { + @NotNull private final ProgressIndicator myIndicator; + + public CancellingOnHeavyProcessListener(@NotNull ProgressIndicator indicator) { + myIndicator = indicator; + } + + @Override + public void processStarted() { + myIndicator.cancel(); + } + + @Override + public void processFinished() { + } + } }