Bug 373790 - Debug view stays busy after Resume

Fixed busy state in variables view when switching frames rapidly.
diff --git a/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/TestModelUpdatesListener.java b/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/TestModelUpdatesListener.java
index ff39eba..c284880 100644
--- a/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/TestModelUpdatesListener.java
+++ b/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/TestModelUpdatesListener.java
@@ -432,7 +432,7 @@
     
     public boolean isFinished(int flags) {
         if (isTimedOut()) {
-            throw new RuntimeException("Timed Out: " + toString(flags));
+           throw new RuntimeException("Timed Out: " + toString(flags));
         }
         
         if (fFailExpectation != null) {
diff --git a/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/UpdateTests.java b/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/UpdateTests.java
index 4c365bc..97de6f9 100644
--- a/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/UpdateTests.java
+++ b/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/UpdateTests.java
@@ -534,7 +534,7 @@
      * </p>
      * @see org.eclipse.debug.internal.ui.viewers.model.ModelContentProvider#rescheduleUpdates
      */
-    public void testCancelUpdates5() throws InterruptedException {
+    public void testCancelUpdatesOnRemoveElementWhileUpdatingSubTree() throws InterruptedException {
         TestModel model = TestModel.simpleMultiLevel();
         fViewer.setAutoExpandLevel(-1);
 
@@ -563,6 +563,80 @@
         while (!fListener.isFinished(ALL_UPDATES_COMPLETE)) if (!fDisplay.readAndDispatch ()) Thread.sleep(0);
     }
 
+    /**
+     * This test forces the viewer to cancel updates upon setInput().
+     * <p>
+     * - Wait until CHILDREN update started then refresh<br>
+     * - Process queued updates in order.<br>
+     * </p>
+     */
+    public void testCanceledUpdatesOnSetInput() throws InterruptedException {
+        TestModel model = TestModel.simpleSingleLevel();
+        fViewer.setAutoExpandLevel(-1);
+
+        // Create the listener
+        fListener.reset(TreePath.EMPTY, model.getRootElement(), -1, false, false); 
+
+        // Set the input into the view and update the view.
+        fViewer.setInput(model.getRootElement());
+        while (!fListener.isFinished()) if (!fDisplay.readAndDispatch ()) Thread.sleep(0);
+        model.validateData(fViewer, TreePath.EMPTY);
+
+        model.setQeueueingUpdate(false);
+        
+        // Refresh the viewer so that updates are generated.
+        fListener.reset();
+        fListener.addChildreCountUpdate(TreePath.EMPTY);
+        model.postDelta(new ModelDelta(model.getRootElement(), IModelDelta.CONTENT));
+        
+        // Wait for the delta to be processed.
+        while (!fListener.isFinished(MODEL_CHANGED_COMPLETE | CHILD_COUNT_UPDATES)) 
+        	if (!fDisplay.readAndDispatch ()) Thread.sleep(0);
+        
+        TestModel model2 = new TestModel();
+        model2.setRoot(new TestElement(model2, "root", new TestElement[0]));
+        fViewer.setInput(model2.getRootElement());
+
+        while (!fListener.isFinished(CONTENT_COMPLETE | VIEWER_UPDATES_RUNNING)) if (!fDisplay.readAndDispatch ()) Thread.sleep(0);
+        
+    }
+
+    /**
+     * This test forces the viewer to cancel updates upon setInput().
+     * <p>
+     * - Wait until CHILDREN update started then refresh<br>
+     * - Process queued updates in order.<br>
+     * </p>
+     */
+    public void testCanceledUpdatesOnSetNullInput() throws InterruptedException {
+        TestModel model = TestModel.simpleSingleLevel();
+        fViewer.setAutoExpandLevel(-1);
+
+        // Create the listener
+        fListener.reset(TreePath.EMPTY, model.getRootElement(), -1, false, false); 
+
+        // Set the input into the view and update the view.
+        fViewer.setInput(model.getRootElement());
+        while (!fListener.isFinished()) if (!fDisplay.readAndDispatch ()) Thread.sleep(0);
+        model.validateData(fViewer, TreePath.EMPTY);
+
+        model.setQeueueingUpdate(false);
+        
+        // Refresh the viewer so that updates are generated.
+        fListener.reset();
+        fListener.addChildreCountUpdate(TreePath.EMPTY);
+        model.postDelta(new ModelDelta(model.getRootElement(), IModelDelta.CONTENT));
+        
+        // Wait for the delta to be processed.
+        while (!fListener.isFinished(MODEL_CHANGED_COMPLETE | CHILD_COUNT_UPDATES)) 
+        	if (!fDisplay.readAndDispatch ()) Thread.sleep(0);
+        
+        fViewer.setInput(null);
+
+        while (!fListener.isFinished(CONTENT_COMPLETE | VIEWER_UPDATES_RUNNING)) if (!fDisplay.readAndDispatch ()) Thread.sleep(0);
+        
+    }
+    
     
     private void completeQueuedUpdatesOfType(TestModel model, Class updateClass) {
         List updatesToComplete = new LinkedList();
diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/TreeModelContentProvider.java b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/TreeModelContentProvider.java
index 386fe8c..20057d5 100644
--- a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/TreeModelContentProvider.java
+++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/TreeModelContentProvider.java
@@ -104,6 +104,12 @@
     private ListenerList fUpdateListeners = new ListenerList();
 
     /**
+     * Flag indicating whether we are currently in a model sequence.
+     * @see IViewerUpdateListener
+     */
+    private boolean fModelSequenceRunning = false;
+    
+    /**
      * Map of updates in progress: element path -> list of requests
      */
     private Map fRequestsInProgress = new HashMap();
@@ -194,7 +200,7 @@
         if (newInput != null) {
             installModelProxy(newInput, TreePath.EMPTY);
             fStateTracker.restoreViewerState(newInput);
-        }
+        } 
     }
 
     public void addViewerUpdateListener(IViewerUpdateListener listener) {
@@ -579,14 +585,14 @@
     void updateStarted(ViewerUpdateMonitor update) {
         Assert.isTrue( getViewer().getDisplay().getThread() == Thread.currentThread() );
         
-        boolean begin = fRequestsInProgress.isEmpty();
         List requests = (List) fRequestsInProgress.get(update.getSchedulingPath());
         if (requests == null) {
             requests = new ArrayList();
             fRequestsInProgress.put(update.getSchedulingPath(), requests);
         }
         requests.add(update);
-        if (begin) {
+        if (!fModelSequenceRunning) {
+        	fModelSequenceRunning = true;
             if (DebugUIPlugin.DEBUG_UPDATE_SEQUENCE && DebugUIPlugin.DEBUG_TEST_PRESENTATION_ID(getPresentationContext())) {
                 DebugUIPlugin.trace("MODEL SEQUENCE BEGINS"); //$NON-NLS-1$
             }
@@ -647,7 +653,8 @@
                         fRequestsInProgress.remove(update.getSchedulingPath());
                     }
             	}
-                if (fRequestsInProgress.isEmpty() && fWaitingRequests.isEmpty()) {
+                if (fRequestsInProgress.isEmpty() && fWaitingRequests.isEmpty() && fModelSequenceRunning) {
+                	fModelSequenceRunning = false;
                     if (DebugUIPlugin.DEBUG_UPDATE_SEQUENCE && DebugUIPlugin.DEBUG_TEST_PRESENTATION_ID(getPresentationContext())) {
                         DebugUIPlugin.trace("MODEL SEQUENCE ENDS"); //$NON-NLS-1$
                     }