Index: branches/HeuristicLab.DebugEngine/DebugEngine.cs
===================================================================
--- branches/HeuristicLab.DebugEngine/DebugEngine.cs	(revision 4827)
+++ branches/HeuristicLab.DebugEngine/DebugEngine.cs	(revision 4871)
@@ -21,8 +21,11 @@
 
 using System;
+using System.Linq;
 using System.Collections.Generic;
 using HeuristicLab.Common;
 using HeuristicLab.Core;
 using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Collections;
+using System.Threading;
 
 namespace HeuristicLab.DebugEngine {
@@ -30,22 +33,199 @@
   [StorableClass]
   [Item("Debug Engine", "Engine for debugging algorithms.")]
-  public class DebugEngine : Engine {
-    private IOperator currentOperator;
-
+  public class DebugEngine : Executable, IEngine {
+
+
+    #region Construction and Cloning
+    
     [StorableConstructor]
-    protected DebugEngine(bool deserializing) : base(deserializing) { }
-    protected DebugEngine(DebugEngine original, Cloner cloner) : base(original, cloner) { }
+    protected DebugEngine(bool deserializing) : base(deserializing) {
+      pausePending = stopPending = false;
+      timer = new System.Timers.Timer(100);
+      timer.AutoReset = true;
+      timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed);
+    }
+    protected DebugEngine(DebugEngine original, Cloner cloner) : base(original, cloner) {
+      if (original.ExecutionState == ExecutionState.Started) throw new InvalidOperationException(string.Format("Clone not allowed in execution state \"{0}\".", ExecutionState));
+      Log = cloner.Clone(original.Log);
+      ExecutionStack = cloner.Clone(original.ExecutionStack);
+      pausePending = original.pausePending;
+      stopPending = original.stopPending;
+      timer = new System.Timers.Timer(100);
+      timer.AutoReset = true;
+      timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed);
+      this.currentOperation = cloner.Clone(original.currentOperation);
+      this.currentOperator = cloner.Clone(original.currentOperator);
+    }
     public DebugEngine()
       : base() {
-    }
-
-    public new Stack<IOperation> ExecutionStack {
-      get { return base.ExecutionStack; }
-    }
-
-    public IAtomicOperation CurrentOperation { get; private set; }
+      Log = new Log();
+      ExecutionStack = new ExecutionStack();
+      pausePending = stopPending = false;
+      timer = new System.Timers.Timer(100);
+      timer.AutoReset = true;
+      timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed);
+    }
 
     public override IDeepCloneable Clone(Cloner cloner) {
       return new DebugEngine(this, cloner);
+    }
+
+    #endregion
+
+    #region Fields and Properties
+
+    [Storable]
+    public ILog Log { get; protected set; }
+
+    [Storable]
+    public ExecutionStack ExecutionStack { get; protected set; }
+
+    private bool pausePending, stopPending;
+    private DateTime lastUpdateTime;
+    private System.Timers.Timer timer;
+      
+    [Storable]
+    private IOperator currentOperator;
+
+    [Storable]
+    private bool ignoreNextBreakpoint;
+
+    [Storable]
+    private IOperation currentOperation;
+    public virtual IOperation CurrentOperation {
+      get { return currentOperation; }
+      private set {
+        if (value == currentOperation)
+          return;
+        currentOperation = value;
+        OnOperationChanged(value);
+      }
+    }
+
+    public virtual IAtomicOperation CurrentAtomicOperation {
+      get { return CurrentOperation as IAtomicOperation; }
+    }
+
+    public virtual IExecutionContext CurrentExecutionContext {
+      get { return CurrentOperation as IExecutionContext;  }
+    }
+
+    #endregion
+
+    #region Events
+
+    public event EventHandler<OperationChangedEventArgs> CurrentOperationChanged;
+
+    protected virtual void OnOperationChanged(IOperation newOperation) {
+      EventHandler<OperationChangedEventArgs> handler = CurrentOperationChanged;
+      if (handler != null) {
+        handler(this, new OperationChangedEventArgs(newOperation));
+      }
+    }
+
+    #endregion
+
+    #region Std Methods
+    public sealed override void Prepare() {
+      base.Prepare();
+      ExecutionStack.Clear();
+      ignoreNextBreakpoint = false;
+      CurrentOperation = null;
+      OnPrepared();
+    }
+    public void Prepare(IOperation initialOperation) {
+      base.Prepare();
+      ExecutionStack.Clear();
+      if (initialOperation != null)
+        ExecutionStack.Add(initialOperation);
+      ignoreNextBreakpoint = false;
+      CurrentOperation = null;
+      OnPrepared();
+    }
+    protected override void OnPrepared() {
+      Log.LogMessage("Engine prepared");
+      base.OnPrepared();
+    }
+
+    public virtual void Step() {
+      OnStarted();
+      lastUpdateTime = DateTime.Now;
+      ignoreNextBreakpoint = true;
+      timer.Start();
+      ProcessNextOperation();      
+      timer.Stop();
+      ExecutionTime += DateTime.Now - lastUpdateTime;
+      ignoreNextBreakpoint = false;
+      OnPaused();
+    }
+
+    public override void Start() {
+      base.Start();
+      CurrentOperation = null;
+      ThreadPool.QueueUserWorkItem(new WaitCallback(Run), null);
+    }
+    
+    protected override void OnStarted() {
+      Log.LogMessage("Engine started");
+      base.OnStarted();
+    }
+
+    public override void Pause() {
+      base.Pause();
+      pausePending = true;
+      if (currentOperator != null) currentOperator.Abort();
+    }
+
+    protected override void OnPaused() {
+      Log.LogMessage("Engine paused");
+      base.OnPaused();
+    }
+
+    public override void Stop() {
+      CurrentOperation = null;
+      base.Stop();
+      stopPending = true;
+      if (currentOperator != null) currentOperator.Abort();
+      ignoreNextBreakpoint = false;
+      if (ExecutionState == ExecutionState.Paused) OnStopped();
+    }
+    
+    protected override void OnStopped() {
+      Log.LogMessage("Engine stopped");
+      base.OnStopped();
+    }
+
+    protected override void OnExceptionOccurred(Exception exception) {
+      Log.LogException(exception);
+      base.OnExceptionOccurred(exception);
+    }
+
+    private void Run(object state) {
+      OnStarted();
+      pausePending = stopPending = false;
+
+      lastUpdateTime = DateTime.Now;
+      timer.Start();
+      while (!pausePending && !stopPending && CanContinue) {
+        ProcessNextOperation();
+      }
+      timer.Stop();
+      ExecutionTime += DateTime.Now - lastUpdateTime;
+
+      if (pausePending) OnPaused();
+      else OnStopped();
+    }
+
+    private void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) {
+      DateTime now = DateTime.Now;
+      ExecutionTime += now - lastUpdateTime;
+      lastUpdateTime = now;
+    }
+    #endregion
+
+    #region Methods
+
+    public virtual bool CanContinue {
+      get { return CurrentOperation != null || ExecutionStack.Count > 0; }
     }
 
@@ -57,59 +237,66 @@
     /// is pushed on the stack again.<br/>
     /// If the execution was successful <see cref="EngineBase.OnOperationExecuted"/> is called.</remarks>
-    protected override void ProcessNextOperation() {
-      currentOperator = null;
-      IOperation next = ExecutionStack.Pop();
-      OperationCollection coll = next as OperationCollection;
-      while (coll != null) {
-        Log.LogMessage("Expanding OperationCollection");
-        for (int i = coll.Count - 1; i >= 0; i--) {
-          ExecutionStack.Push(coll[i]);
+    protected virtual void ProcessNextOperation() {
+      try {
+        IAtomicOperation atomicOperation = CurrentOperation as IAtomicOperation;
+        OperationCollection operations = CurrentOperation as OperationCollection;
+        if (atomicOperation != null && operations != null)
+          throw new InvalidOperationException("Current operation is both atomic and an operation collection");
+
+        if (atomicOperation != null) {
+          Log.LogMessage(string.Format("Performing atomic operation {0}", Name(atomicOperation)));
+          PerformAtomicOperation(atomicOperation);
+        } else if (operations != null) {
+          Log.LogMessage("Expanding operation collection");
+          ExpandOperationCollection(operations);
+        } else if (ExecutionStack.Count > 0) {
+          Log.LogMessage("Poping execution stack");
+          CurrentOperation = ExecutionStack.Last();
+          ExecutionStack.RemoveAt(ExecutionStack.Count - 1);
+        } else {
+          Log.LogMessage("Nothing to do");
         }
-        next = ExecutionStack.Count > 0 ? ExecutionStack.Pop() : null;
-        coll = next as OperationCollection;
-      }
-      IAtomicOperation operation = next as IAtomicOperation;
+      } catch (Exception x) {
+        OnExceptionOccurred(x);
+      }
+    }
+
+    protected virtual void PerformAtomicOperation(IAtomicOperation operation) {
       if (operation != null) {
-        Log.LogMessage("Preparing IAtomicOperation");
+        if (operation.Operator.Breakpoint) {
+          if (ignoreNextBreakpoint) {
+            ignoreNextBreakpoint = false;
+          } else {
+            ignoreNextBreakpoint = true;
+            Log.LogMessage(string.Format("Breaking before: {0}", Name(operation)));
+            Pause();
+            return;
+          }
+        }
         try {
           currentOperator = operation.Operator;
-          CurrentOperation = operation;
-          if (operation.Operator.Breakpoint) {
-            Log.LogMessage(string.Format("Breakpoint: Before {0}", operation.Operator.Name != string.Empty ? operation.Operator.Name : operation.Operator.ItemName));
-            Pause();
+          IOperation successor = operation.Operator.Execute((IExecutionContext)operation);
+          CurrentOperation = null;
+          currentOperator = null;
+          if (successor != null) {
+            ExecutionStack.Add(successor);
           }
-          Log.LogMessage("Executing IAtomicOperation");
-          ExecutionStack.Push(operation.Operator.Execute((IExecutionContext)operation));
         } catch (Exception ex) {
           OnExceptionOccurred(new OperatorExecutionException(operation.Operator, ex));
           Pause();
         }
-      } else {
-        Log.LogMessage("Nothing to do");
-        CurrentOperation = null;
-      }
-    }
-
-    public override void Pause() {
-      base.Pause();
-      if (currentOperator != null) currentOperator.Abort();
-    }
-    public override void Stop() {
-      base.Stop();
-      if (currentOperator != null) currentOperator.Abort();
-    }
-
-    public virtual void Step() {
-      OnStarted();
-      var lastUpdateTime = DateTime.Now;
-      if (ExecutionStack.Count > 0) {
-        while (ExecutionStack.Count > 0 && ExecutionStack.Peek() == null)
-          ExecutionStack.Pop();
-        if (ExecutionStack.Count > 0)
-          ProcessNextOperation();
-      }
-      ExecutionTime += DateTime.Now - lastUpdateTime;
-      OnPaused();
-    }
+      }
+    }
+
+    protected virtual void ExpandOperationCollection(OperationCollection operations) {
+      ExecutionStack.AddRange(operations.Reverse());
+      CurrentOperation = null;
+    }
+
+    protected virtual string Name(IAtomicOperation operation) {
+      return string.IsNullOrEmpty(operation.Operator.Name) ? operation.Operator.ItemName : operation.Operator.Name;
+    }
+
+    #endregion
   }
 }
