From 4451b1b3be64590af1de8a2e526e071ff89de3c7 Mon Sep 17 00:00:00 2001 From: irengrig Date: Thu, 29 Dec 2011 15:17:38 +0400 Subject: [PATCH] VSC: better suspend logic for continuation, to avoid potential duplicate tasks after suspend-awake (separate progress runner) --- .../util/continuation/GeneralRunner.java | 25 ++++++++++++++----- .../util/continuation/SameProgressRunner.java | 19 +++++++------- .../continuation/SeparatePiecesRunner.java | 6 ++--- 3 files changed, 31 insertions(+), 19 deletions(-) diff --git a/platform/vcs-impl/src/com/intellij/util/continuation/GeneralRunner.java b/platform/vcs-impl/src/com/intellij/util/continuation/GeneralRunner.java index 1ddfbb48bc48..3a3e1e7bbe3b 100644 --- a/platform/vcs-impl/src/com/intellij/util/continuation/GeneralRunner.java +++ b/platform/vcs-impl/src/com/intellij/util/continuation/GeneralRunner.java @@ -28,6 +28,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.*; +import java.util.concurrent.atomic.AtomicInteger; /** * @author irengrig @@ -39,7 +40,7 @@ abstract class GeneralRunner implements ContinuationContext { protected final boolean myCancellable; protected final List myQueue; protected final Object myQueueLock; - protected volatile boolean myTriggerSuspend; + private boolean myTriggerSuspend; protected ProgressIndicator myIndicator; protected final Map myDisasters; private final List> myTasksPatchers; @@ -53,6 +54,7 @@ abstract class GeneralRunner implements ContinuationContext { myDisasters = new HashMap(); myHandlersMap = new HashMap, Consumer>(); myTasksPatchers = new ArrayList>(); + myTriggerSuspend = false; } public void addExceptionHandler(final Class clazz, final Consumer consumer) { @@ -113,7 +115,21 @@ abstract class GeneralRunner implements ContinuationContext { } public void suspend() { - myTriggerSuspend = true; + synchronized (myQueueLock) { + myTriggerSuspend = true; + } + } + + protected boolean getSuspendFlag() { + synchronized (myQueueLock) { + return myTriggerSuspend; + } + } + + protected void clearSuspend() { + synchronized (myQueueLock) { + myTriggerSuspend = false; + } } @Override @@ -241,13 +257,10 @@ abstract class GeneralRunner implements ContinuationContext { ping(); } - // null - no more tasks or suspend + // null - no more tasks @Nullable protected TaskDescriptor getNextMatching() { while (true) { - if (myTriggerSuspend) { - return null; - } synchronized (myQueueLock) { if (myQueue.isEmpty()) return null; TaskDescriptor current = myQueue.remove(0); diff --git a/platform/vcs-impl/src/com/intellij/util/continuation/SameProgressRunner.java b/platform/vcs-impl/src/com/intellij/util/continuation/SameProgressRunner.java index 5ab3bab2364b..a2c625b426d8 100644 --- a/platform/vcs-impl/src/com/intellij/util/continuation/SameProgressRunner.java +++ b/platform/vcs-impl/src/com/intellij/util/continuation/SameProgressRunner.java @@ -52,7 +52,7 @@ public class SameProgressRunner extends GeneralRunner { @Override public void ping() { - myTriggerSuspend = false; + clearSuspend(); if (Thread.currentThread().equals(myInitThread)) { pingInSourceThread(); } else { @@ -66,17 +66,16 @@ public class SameProgressRunner extends GeneralRunner { // stop if project is being disposed if (! myProject.isOpen()) return; + if (getSuspendFlag()) { + mySemaphore.down(); + while (getSuspendFlag()) { + mySemaphore.waitFor(500); + } + } + final TaskDescriptor current = getNextMatching(); if (current == null) { - if (myTriggerSuspend) { - mySemaphore.down(); - while (myTriggerSuspend) { - mySemaphore.waitFor(500); - } - continue; - } else { - return; - } + return; } if (Where.AWT.equals(current.getWhere())) { diff --git a/platform/vcs-impl/src/com/intellij/util/continuation/SeparatePiecesRunner.java b/platform/vcs-impl/src/com/intellij/util/continuation/SeparatePiecesRunner.java index a8b5bb7cb409..9bff264d55d2 100644 --- a/platform/vcs-impl/src/com/intellij/util/continuation/SeparatePiecesRunner.java +++ b/platform/vcs-impl/src/com/intellij/util/continuation/SeparatePiecesRunner.java @@ -40,6 +40,7 @@ public class SeparatePiecesRunner extends GeneralRunner { @CalledInAwt public void ping() { + clearSuspend(); if (! ApplicationManager.getApplication().isDispatchThread()) { Runnable command = new Runnable() { public void run() { @@ -52,15 +53,14 @@ public class SeparatePiecesRunner extends GeneralRunner { } } + @CalledInAwt private void pingImpl() { while (true) { // stop if project is being disposed if (! myProject.isDefault() && ! myProject.isOpen()) return; + if (getSuspendFlag()) return; final TaskDescriptor current = getNextMatching(); if (current == null) { - synchronized (myQueueLock) { - myTriggerSuspend = false; - } return; }