/*
 * Copyright 2000-2009 JetBrains s.r.o.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.intellij.debugger.engine.events;

import com.intellij.debugger.engine.DebuggerManagerThreadImpl;
import com.intellij.debugger.engine.SuspendContextImpl;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.util.containers.Stack;

/**
 * Created by IntelliJ IDEA.
 * User: lex
 * Date: Feb 24, 2004
 * Time: 7:01:31 PM
 * Performs contextAction when evaluation is available in suspend context
 */
public abstract class SuspendContextCommandImpl extends DebuggerCommandImpl {
  private static final Logger LOG = Logger.getInstance("#com.intellij.debugger.engine.SuspendContextCommand");
  private final SuspendContextImpl mySuspendContext;

  protected SuspendContextCommandImpl(SuspendContextImpl suspendContext) {
    mySuspendContext = suspendContext;
  }

  public abstract void contextAction() throws Exception;

  public final void action() throws Exception {
    if(LOG.isDebugEnabled()) {
      LOG.debug("trying " + this);
    }

    final SuspendContextImpl suspendContext = getSuspendContext();

    if (suspendContext == null) {
      if (LOG.isDebugEnabled()) {
        LOG.debug("skip processing - context is null " + this);
      }
      notifyCancelled();
      return;
    }

    if(suspendContext.myInProgress) {
      suspendContext.postponeCommand(this);
    }
    else {
      try {
        if(!suspendContext.isResumed()) {
          suspendContext.myInProgress = true;
          contextAction();
        }
        else {
          notifyCancelled();
        }
      }
      finally{
        suspendContext.myInProgress = false;
        SuspendContextCommandImpl postponed = suspendContext.pollPostponedCommand();
        if (postponed != null) {
          final Stack<SuspendContextCommandImpl> stack = new Stack<SuspendContextCommandImpl>();
          while (postponed != null) {
            stack.push(postponed);
            postponed = suspendContext.pollPostponedCommand();
          }
          final DebuggerManagerThreadImpl managerThread = suspendContext.getDebugProcess().getManagerThread();
          while (!stack.isEmpty()) {
            managerThread.pushBack(stack.pop());
          }
        }
      }
    }
  }

  public SuspendContextImpl getSuspendContext() {
    return mySuspendContext;
  }
}

@@ -2177,16 +2177,65 @@
         
+if (suspendContext.isResumed()) %7B%0A          for (
 SuspendC
@@ -2294,33 +2294,272 @@
 tponedCommand();
-%0A
+ postponed != null; postponed = suspendContext.pollPostponedCommand()) %7B%0A            postponed.notifyCancelled();%0A          %7D%0A        %7D%0A        else %7B%0A          SuspendContextCommandImpl postponed = suspendContext.pollPostponedCommand();%0A  
         if (post
@@ -2581,24 +2581,26 @@
 %7B%0A          
+ 
+ 
 final Stack%3C
@@ -2680,24 +2680,26 @@
 ;%0A          
+  
 while (postp
@@ -2706,32 +2706,34 @@
 oned != null) %7B%0A
+  
             stac
@@ -2755,32 +2755,34 @@
 d);%0A            
+  
 postponed = susp
@@ -2818,32 +2818,34 @@
 nd();%0A          
+  
 %7D%0A          fina
@@ -2836,24 +2836,26 @@
 %7D%0A          
+ 
+ 
 final Debugg
@@ -2949,24 +2949,26 @@
 ;%0A          
+  
 while (!stac
@@ -2978,24 +2978,26 @@
 sEmpty()) %7B%0A
+  
             
@@ -3033,16 +3033,30 @@
 pop());%0A
+            %7D%0A
         

fix "not resumed" assertion