VSC: better suspend logic for continuation, to avoid potential duplicate tasks after suspend-awake (separate progress runner)

This commit is contained in:
irengrig
2011-12-29 15:17:38 +04:00
parent 49166128a1
commit 4451b1b3be
3 changed files with 31 additions and 19 deletions
@@ -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<TaskDescriptor> myQueue;
protected final Object myQueueLock;
protected volatile boolean myTriggerSuspend;
private boolean myTriggerSuspend;
protected ProgressIndicator myIndicator;
protected final Map<Object, Object> myDisasters;
private final List<Consumer<TaskDescriptor>> myTasksPatchers;
@@ -53,6 +54,7 @@ abstract class GeneralRunner implements ContinuationContext {
myDisasters = new HashMap<Object, Object>();
myHandlersMap = new HashMap<Class<? extends Exception>, Consumer<Exception>>();
myTasksPatchers = new ArrayList<Consumer<TaskDescriptor>>();
myTriggerSuspend = false;
}
public <T extends Exception> void addExceptionHandler(final Class<T> clazz, final Consumer<T> 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);
@@ -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())) {
@@ -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;
}