mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
call ReadTask.onCanceled on EDT, only once and only on cancellations caused by write actions
This commit is contained in:
+16
-11
@@ -22,13 +22,18 @@ 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;
|
||||
|
||||
/**
|
||||
* Methods in this class are used to equip long background processes which take read actions with a special listener
|
||||
* that fires when a write action is about to begin, and cancels corresponding progress indicators to avoid blocking the UI.
|
||||
* These processes should be ready to get {@link com.intellij.openapi.progress.ProcessCanceledException} at any moment.
|
||||
* Processes may want to react on cancellation event by restarting the activity, see
|
||||
* {@link com.intellij.openapi.progress.util.ReadTask#onCanceled(com.intellij.openapi.progress.ProgressIndicator)} for that.
|
||||
*
|
||||
* @author gregsh
|
||||
*/
|
||||
public class ProgressIndicatorUtils {
|
||||
@@ -59,15 +64,22 @@ public class ProgressIndicatorUtils {
|
||||
public static void scheduleWithWriteActionPriority(@NotNull final ProgressIndicator progressIndicator,
|
||||
@NotNull final Executor executor,
|
||||
@NotNull final ReadTask readTask) {
|
||||
AppUIUtil.invokeOnEdt(new Runnable() {
|
||||
final Application application = ApplicationManager.getApplication();
|
||||
// later even if on EDT
|
||||
// to avoid tasks eagerly restarting immediately, allocating many pooled threads
|
||||
// which get cancelled too soon when a next write action arrives in the same EDT batch
|
||||
// (can happen when processing multiple VFS events or writing multiple files on save)
|
||||
application.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final Application application = ApplicationManager.getApplication();
|
||||
application.assertIsDispatchThread();
|
||||
final ApplicationAdapter listener = new ApplicationAdapter() {
|
||||
@Override
|
||||
public void beforeWriteActionStart(Object action) {
|
||||
progressIndicator.cancel();
|
||||
if (!progressIndicator.isCanceled()) {
|
||||
progressIndicator.cancel();
|
||||
readTask.onCanceled(progressIndicator);
|
||||
}
|
||||
}
|
||||
};
|
||||
application.addApplicationListener(listener);
|
||||
@@ -100,8 +112,6 @@ public class ProgressIndicatorUtils {
|
||||
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
|
||||
@@ -112,11 +122,6 @@ public class ProgressIndicatorUtils {
|
||||
}
|
||||
catch (ProcessCanceledException ignore) {
|
||||
}
|
||||
finally {
|
||||
if (progressIndicator.isCanceled()) {
|
||||
task.onCanceled(progressIndicator);
|
||||
}
|
||||
}
|
||||
}
|
||||
}, progressIndicator);
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ public interface ReadTask {
|
||||
void computeInReadAction(@NotNull ProgressIndicator indicator);
|
||||
|
||||
/**
|
||||
* Is invoked on the background computation thread whenever the computation is canceled by a write action.
|
||||
* Is invoked on Swing thread whenever the computation is canceled by a write action.
|
||||
* A likely implementation is to restart the computation, maybe based on the new state of the system.
|
||||
*/
|
||||
void onCanceled(@NotNull ProgressIndicator indicator);
|
||||
|
||||
@@ -160,14 +160,9 @@ public class EditorNotificationsImpl extends EditorNotifications {
|
||||
|
||||
@Override
|
||||
public void onCanceled(@NotNull ProgressIndicator ignored) {
|
||||
UIUtil.invokeLaterIfNeeded(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (getCurrentProgress(file) == indicator) {
|
||||
updateNotifications(file);
|
||||
}
|
||||
}
|
||||
});
|
||||
if (getCurrentProgress(file) == indicator) {
|
||||
updateNotifications(file);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
+24
-29
@@ -270,42 +270,37 @@ public class MvcModuleStructureSynchronizer extends AbstractProjectComponent {
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
app.invokeLater(new Runnable() {
|
||||
|
||||
final Set<Pair<Object, SyncAction>> orderSnapshot = takeOrderSnapshot();
|
||||
ProgressIndicatorUtils.scheduleWithWriteActionPriority(new ReadTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
final Set<Pair<Object, SyncAction>> orderSnapshot = takeOrderSnapshot();
|
||||
ProgressIndicatorUtils.scheduleWithWriteActionPriority(new ReadTask() {
|
||||
public void computeInReadAction(@NotNull ProgressIndicator indicator) {
|
||||
if (!isUpToDate()) {
|
||||
indicator.cancel();
|
||||
return;
|
||||
}
|
||||
|
||||
final Set<Trinity<Module, SyncAction, MvcFramework>> actions = computeRawActions(orderSnapshot);
|
||||
app.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void computeInReadAction(@NotNull ProgressIndicator indicator) {
|
||||
public void run() {
|
||||
if (!isUpToDate()) {
|
||||
indicator.cancel();
|
||||
return;
|
||||
scheduleRunActions();
|
||||
}
|
||||
else {
|
||||
runActions(actions);
|
||||
}
|
||||
|
||||
final Set<Trinity<Module, SyncAction, MvcFramework>> actions = computeRawActions(orderSnapshot);
|
||||
app.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!isUpToDate()) {
|
||||
scheduleRunActions();
|
||||
}
|
||||
else {
|
||||
runActions(actions);
|
||||
}
|
||||
}
|
||||
}, ModalityState.NON_MODAL);
|
||||
}
|
||||
}, ModalityState.NON_MODAL);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCanceled(@NotNull ProgressIndicator indicator) {
|
||||
scheduleRunActions();
|
||||
}
|
||||
@Override
|
||||
public void onCanceled(@NotNull ProgressIndicator indicator) {
|
||||
scheduleRunActions();
|
||||
}
|
||||
|
||||
private boolean isUpToDate() {
|
||||
return !myProject.isDisposed() && orderSnapshot.equals(takeOrderSnapshot());
|
||||
}
|
||||
});
|
||||
private boolean isUpToDate() {
|
||||
return !myProject.isDisposed() && orderSnapshot.equals(takeOrderSnapshot());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user