project leak: explicitly wait for project scan in background to complete

This commit is contained in:
Alexey Kudravtsev
2017-02-07 14:36:46 +03:00
parent 6b43161e60
commit f374cc7d19
@@ -32,7 +32,10 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.ide.PooledThreadExecutor;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import java.util.concurrent.Future;
import java.util.function.BiConsumer;
/**
* Methods in this class are used to equip long background processes which take read actions with a special listener
@@ -60,16 +63,23 @@ public class ProgressIndicatorUtils {
return progress;
}
@NotNull
public static Future<?> submitWithWriteActionPriority(@NotNull ReadTask task) {
return scheduleWithWriteActionPriority(new ProgressIndicatorBase(), task);
}
public static void scheduleWithWriteActionPriority(@NotNull ReadTask task) {
scheduleWithWriteActionPriority(new ProgressIndicatorBase(), task);
submitWithWriteActionPriority(task);
}
public static void scheduleWithWriteActionPriority(@NotNull ProgressIndicator progressIndicator, @NotNull ReadTask readTask) {
scheduleWithWriteActionPriority(progressIndicator, PooledThreadExecutor.INSTANCE, readTask);
@NotNull
public static Future<?> scheduleWithWriteActionPriority(@NotNull ProgressIndicator progressIndicator, @NotNull ReadTask readTask) {
return scheduleWithWriteActionPriority(progressIndicator, PooledThreadExecutor.INSTANCE, readTask);
}
public static void scheduleWithWriteActionPriority(@NotNull Executor executor, @NotNull ReadTask task) {
scheduleWithWriteActionPriority(new ProgressIndicatorBase(), executor, task);
@NotNull
public static Future<?> scheduleWithWriteActionPriority(@NotNull Executor executor, @NotNull ReadTask task) {
return scheduleWithWriteActionPriority(new ProgressIndicatorBase(), executor, task);
}
/**
@@ -148,9 +158,10 @@ public class ProgressIndicatorUtils {
return wasCancelled.get() != Boolean.TRUE;
}
public static void scheduleWithWriteActionPriority(@NotNull final ProgressIndicator progressIndicator,
@NotNull final Executor executor,
@NotNull final ReadTask readTask) {
@NotNull
public static Future<?> scheduleWithWriteActionPriority(@NotNull final ProgressIndicator progressIndicator,
@NotNull final Executor executor,
@NotNull final ReadTask readTask) {
final Application application = ApplicationManager.getApplication();
// invoke later even if on EDT
// to avoid tasks eagerly restarting immediately, allocating many pooled threads
@@ -160,9 +171,13 @@ public class ProgressIndicatorUtils {
// use SwingUtilities instead of application.invokeLater
// to tolerate any immediate modality changes (e.g. https://youtrack.jetbrains.com/issue/IDEA-135180)
CompletableFuture<?> future = new CompletableFuture<>();
//noinspection SSBasedInspection
EdtInvocationManager.getInstance().invokeLater(() -> {
if (application.isDisposed()) return;
if (application.isDisposed()) {
future.complete(null);
return;
}
final ApplicationAdapter listener = new ApplicationAdapter() {
@Override
public void beforeWriteActionStart(@NotNull Object action) {
@@ -173,35 +188,34 @@ public class ProgressIndicatorUtils {
}
};
application.addApplicationListener(listener);
future.whenComplete((BiConsumer<Object, Throwable>)(o, throwable) -> application.removeApplicationListener(listener));
try {
executor.execute(new Runnable() {
@Override
public void run() {
boolean continued = false;
try {
final ReadTask.Continuation continuation = runUnderProgress(progressIndicator, readTask);
continued = continuation != null;
if (continuation != null) {
application.invokeLater(new Runnable() {
@Override
public void run() {
application.removeApplicationListener(listener);
final ReadTask.Continuation continuation = runUnderProgress(progressIndicator, readTask);
if (continuation == null) {
future.complete(null);
}
else {
application.invokeLater(new Runnable() {
@Override
public void run() {
try {
if (!progressIndicator.isCanceled()) {
continuation.getAction().run();
}
}
@Override
public String toString() {
return "continuation of " + readTask;
finally {
future.complete(null);
}
}, continuation.getModalityState());
}
}
finally {
if (!continued) {
application.removeApplicationListener(listener);
}
}
@Override
public String toString() {
return "continuation of " + readTask;
}
}, continuation.getModalityState());
}
}
@@ -213,9 +227,11 @@ public class ProgressIndicatorUtils {
}
catch (RuntimeException | Error e) {
application.removeApplicationListener(listener);
future.completeExceptionally(e);
throw e;
}
});
return future;
}
private static ReadTask.Continuation runUnderProgress(@NotNull final ProgressIndicator progressIndicator, @NotNull final ReadTask task) {