/// <summary> /// Main method run on the simulation thread /// </summary> private void SimulationThreadProc() { try { ThreadCommand state = ThreadCommand.Break; // Break when returning to this number of stack frames // Used by StepOver and StepReturn int? stepFrameCount = null; // Starting command processing loop for (; ; ) { ThreadCommand cmd = ThreadCommand.Nop; // If we're doing nothing, block for the next command if (state == ThreadCommand.Break) cmd = commandQueue.Take(); // Process any commands do { switch (cmd) { case ThreadCommand.Nop: // Ignore break; case ThreadCommand.Destroy: // Destroy thread return; case ThreadCommand.Break: // Break if we're not already if (state != ThreadCommand.Break) { state = ThreadCommand.Break; OnBreakEvent(new BreakEventArgs(BreakEventReason.BreakMethod)); } break; default: // Cause something to run unless we are doing something already if (state == ThreadCommand.Break) state = cmd; break; } } while (commandQueue.TryTake(out cmd)); // Destroyed? if (state == ThreadCommand.Destroy) break; // Run one step if we need to if (state != ThreadCommand.Break) { try { switch (state) { case ThreadCommand.StepInto: // Execute one step and break Simulator.StepInstruction(); state = ThreadCommand.Break; OnBreakEvent(new BreakEventArgs(BreakEventReason.Step)); break; case ThreadCommand.StepOver: // Set return frame count stepFrameCount = Simulator.CallStack.Count; // Convert to continue state = ThreadCommand.Continue; goto case ThreadCommand.Continue; case ThreadCommand.StepReturn: // Set return frame count stepFrameCount = Simulator.CallStack.Count - 1; // Convert to continue state = ThreadCommand.Continue; goto case ThreadCommand.Continue; case ThreadCommand.Continue: // Execute one step Simulator.StepInstruction(); // Check for breakpoints BreakEventArgs breakArgs = null; if (Simulator.CallStack.Count <= stepFrameCount) breakArgs = new BreakEventArgs(BreakEventReason.Step); else if (IsBreakpointSet(Simulator.ProgramCounter)) breakArgs = new BreakEventArgs(BreakEventReason.Breakpoint); // Raise break event if (breakArgs != null) { stepFrameCount = null; state = ThreadCommand.Break; OnBreakEvent(breakArgs); } break; } } catch (SimulationException e) { // Break on exception state = ThreadCommand.Break; OnBreakEvent(new BreakEventArgs(e)); } } } } finally { // Destroy queue commandQueue.Dispose(); } }
/// <summary> /// Called when a break even occurs /// </summary> /// <param name="e">event arguments</param> protected virtual void OnBreakEvent(BreakEventArgs e) { if (BreakEvent != null) BreakEvent(this, e); }