mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
fixed ProgressUtils: removed runWithWritePriority since it is inherently racy, remove listener only after Future completion
This commit is contained in:
@@ -20,6 +20,7 @@ import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.progress.ProcessCanceledException;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.progress.util.ProgressIndicatorBase;
|
||||
import com.intellij.openapi.progress.util.ProgressIndicatorUtils;
|
||||
import com.intellij.openapi.progress.util.ReadTask;
|
||||
import com.intellij.openapi.project.DumbService;
|
||||
@@ -40,7 +41,6 @@ import org.jetbrains.jps.api.CmdlineRemoteProto;
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
/**
|
||||
* @author Eugene Zhuravlev
|
||||
@@ -82,12 +82,7 @@ public abstract class DefaultMessageHandler implements BuilderMessageHandler {
|
||||
break;
|
||||
case CONSTANT_SEARCH_TASK:
|
||||
final CmdlineRemoteProto.Message.BuilderMessage.ConstantSearchTask task = msg.getConstantSearchTask();
|
||||
myTaskExecutor.submit(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
handleConstantSearchTask(channel, sessionId, task);
|
||||
}
|
||||
});
|
||||
handleConstantSearchTask(channel, sessionId, task);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -97,30 +92,29 @@ public abstract class DefaultMessageHandler implements BuilderMessageHandler {
|
||||
protected abstract void handleBuildEvent(UUID sessionId, CmdlineRemoteProto.Message.BuilderMessage.BuildEvent event);
|
||||
|
||||
private void handleConstantSearchTask(final Channel channel, final UUID sessionId, final CmdlineRemoteProto.Message.BuilderMessage.ConstantSearchTask task) {
|
||||
while (true) {
|
||||
final AtomicBoolean canceled = new AtomicBoolean(false);
|
||||
DumbService.getInstance(myProject).waitForSmartMode();
|
||||
ProgressIndicatorUtils.runWithWriteActionPriority(new ReadTask() {
|
||||
@Override
|
||||
public void computeInReadAction(@NotNull ProgressIndicator indicator) {
|
||||
if (DumbService.isDumb(myProject)) {
|
||||
canceled.set(true);
|
||||
return;
|
||||
}
|
||||
|
||||
ProgressIndicatorUtils.scheduleWithWriteActionPriority(new ProgressIndicatorBase(), myTaskExecutor, new ReadTask() {
|
||||
@Override
|
||||
public void computeInReadAction(@NotNull ProgressIndicator indicator) {
|
||||
if (DumbService.isDumb(myProject)) {
|
||||
onCanceled(indicator);
|
||||
}
|
||||
else {
|
||||
doHandleConstantSearchTask(channel, sessionId, task);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCanceled(@NotNull ProgressIndicator indicator) {
|
||||
canceled.set(true);
|
||||
}
|
||||
});
|
||||
if (!canceled.get()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCanceled(@NotNull ProgressIndicator indicator) {
|
||||
DumbService.getInstance(myProject).runWhenSmart(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
handleConstantSearchTask(channel, sessionId, task);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void doHandleConstantSearchTask(Channel channel, UUID sessionId, CmdlineRemoteProto.Message.BuilderMessage.ConstantSearchTask task) {
|
||||
final String ownerClassName = task.getOwnerClassName();
|
||||
final String fieldName = task.getFieldName();
|
||||
|
||||
+59
-75
@@ -22,7 +22,11 @@ import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.progress.ProcessCanceledException;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.ui.AppUIUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.ide.PooledThreadExecutor;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
/**
|
||||
* @author gregsh
|
||||
@@ -44,96 +48,76 @@ public class ProgressIndicatorUtils {
|
||||
return progress;
|
||||
}
|
||||
|
||||
public static void runWithWriteActionPriority(@NotNull final Runnable action) {
|
||||
runWithWriteActionPriority(new ReadTask() {
|
||||
@Override
|
||||
public void computeInReadAction(@NotNull ProgressIndicator indicator) {
|
||||
action.run();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCanceled(@NotNull ProgressIndicator indicator) {
|
||||
}
|
||||
});
|
||||
public static void scheduleWithWriteActionPriority(@NotNull ReadTask task) {
|
||||
scheduleWithWriteActionPriority(new ProgressIndicatorBase(), task);
|
||||
}
|
||||
|
||||
public static void runWithWriteActionPriority(@NotNull final ReadTask task) {
|
||||
runWithWriteActionPriority(new ProgressIndicatorBase(), task);
|
||||
public static void scheduleWithWriteActionPriority(@NotNull ProgressIndicator progressIndicator, @NotNull ReadTask readTask) {
|
||||
scheduleWithWriteActionPriority(progressIndicator, PooledThreadExecutor.INSTANCE, readTask);
|
||||
}
|
||||
|
||||
private static void surroundWithListener(@NotNull final ProgressIndicator progressIndicator, @NotNull Runnable runnable) {
|
||||
final ApplicationAdapter listener = new ApplicationAdapter() {
|
||||
@Override
|
||||
public void beforeWriteActionStart(Object action) {
|
||||
progressIndicator.cancel();
|
||||
}
|
||||
};
|
||||
final Application application = ApplicationManager.getApplication();
|
||||
application.addApplicationListener(listener);
|
||||
try {
|
||||
runnable.run();
|
||||
}
|
||||
finally {
|
||||
application.removeApplicationListener(listener);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void runWithWriteActionPriority(@NotNull final ProgressIndicator progressIndicator, @NotNull final ReadTask task) {
|
||||
surroundWithListener(progressIndicator, new Runnable() {
|
||||
public static void scheduleWithWriteActionPriority(@NotNull final ProgressIndicator progressIndicator,
|
||||
@NotNull final Executor executor,
|
||||
@NotNull final ReadTask readTask) {
|
||||
AppUIUtil.invokeOnEdt(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
runUnderProgress(progressIndicator, task);
|
||||
final Application application = ApplicationManager.getApplication();
|
||||
application.assertIsDispatchThread();
|
||||
final ApplicationAdapter listener = new ApplicationAdapter() {
|
||||
@Override
|
||||
public void beforeWriteActionStart(Object action) {
|
||||
progressIndicator.cancel();
|
||||
}
|
||||
};
|
||||
application.addApplicationListener(listener);
|
||||
try {
|
||||
executor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
runUnderProgress(progressIndicator, readTask);
|
||||
}
|
||||
finally {
|
||||
application.removeApplicationListener(listener);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (RuntimeException e) {
|
||||
application.removeApplicationListener(listener);
|
||||
throw e;
|
||||
}
|
||||
catch (Error e) {
|
||||
application.removeApplicationListener(listener);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static void runUnderProgress(@NotNull final ProgressIndicator progressIndicator, @NotNull final ReadTask task) {
|
||||
ProgressManager.getInstance().runProcess(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
// This read action can possible last for a long time, we want it to stop immediately on the first write access.
|
||||
// For this purpose we launch it under empty progress and invoke progressIndicator#cancel on write access to avoid possible write lock delays.
|
||||
try {
|
||||
ApplicationManager.getApplication().runReadAction(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
task.computeInReadAction(progressIndicator);
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (ProcessCanceledException ignore) {
|
||||
}
|
||||
finally {
|
||||
if (progressIndicator.isCanceled()) {
|
||||
task.onCanceled(progressIndicator);
|
||||
}
|
||||
}
|
||||
}
|
||||
}, progressIndicator);
|
||||
}
|
||||
|
||||
public static void scheduleWithWriteActionPriority(@NotNull final ReadTask task) {
|
||||
scheduleWithWriteActionPriority(new ProgressIndicatorBase(), task);
|
||||
}
|
||||
|
||||
public static void scheduleWithWriteActionPriority(@NotNull final ProgressIndicator indicator, @NotNull final ReadTask task) {
|
||||
// we have to attach listeners in EDT to avoid "fire write action started while attach listeners from another thread" race condition
|
||||
ApplicationManager.getApplication().invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
surroundWithListener(indicator, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
ApplicationManager.getApplication().executeOnPooledThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
runUnderProgress(indicator, task);
|
||||
}
|
||||
});
|
||||
// This read action can possible last for a long time, we want it to stop immediately on the first write access.
|
||||
// For this purpose we launch it under empty progress and invoke progressIndicator#cancel on write access to avoid possible write lock delays.
|
||||
try {
|
||||
ApplicationManager.getApplication().runReadAction(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
task.computeInReadAction(progressIndicator);
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (ProcessCanceledException ignore) {
|
||||
}
|
||||
finally {
|
||||
if (progressIndicator.isCanceled()) {
|
||||
task.onCanceled(progressIndicator);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}, progressIndicator);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,13 +102,7 @@ public class EditorNotificationsImpl extends EditorNotifications {
|
||||
task.computeInReadAction(indicator);
|
||||
}
|
||||
else {
|
||||
final ProgressIndicator indicator1 = indicator;
|
||||
myExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
ProgressIndicatorUtils.runWithWriteActionPriority(indicator1, task);
|
||||
}
|
||||
});
|
||||
ProgressIndicatorUtils.scheduleWithWriteActionPriority(indicator, myExecutor, task);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user