mirror of
https://github.com/ZuneDev/MicrosoftIris.git
synced 2026-07-27 13:13:29 -07:00
Implement basic interpreter execution controls
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
namespace Microsoft.Iris.Debug.Data;
|
||||
|
||||
public enum InterpreterCommand : byte
|
||||
{
|
||||
Continue,
|
||||
Break,
|
||||
Step,
|
||||
}
|
||||
@@ -6,4 +6,7 @@ public enum DebuggerMessageType : int
|
||||
|
||||
InterpreterOpCode,
|
||||
DispatcherStep,
|
||||
|
||||
UpdateBreakpoint,
|
||||
InterpreterCommand,
|
||||
}
|
||||
|
||||
@@ -10,6 +10,10 @@ public interface IDebuggerClient
|
||||
/// </summary>
|
||||
Uri ConnectionUri { get; }
|
||||
|
||||
InterpreterCommand DebuggerCommand { get; set; }
|
||||
|
||||
event Action<InterpreterCommand> InterpreterStateChanged;
|
||||
|
||||
/// <summary>
|
||||
/// Fired when the UIX interpreter steps forward.
|
||||
/// </summary>
|
||||
@@ -19,4 +23,6 @@ public interface IDebuggerClient
|
||||
/// Fired when the UIX dispatcher executes another call from the queue.
|
||||
/// </summary>
|
||||
event Action<string> DispatcherStep;
|
||||
|
||||
void UpdateBreakpoint(Breakpoint breakpoint);
|
||||
}
|
||||
|
||||
@@ -4,15 +4,17 @@ namespace Microsoft.Iris.Debug;
|
||||
|
||||
internal interface IDebuggerServer
|
||||
{
|
||||
InterpreterCommand DebuggerCommand { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Logs the context, opcode, and arguments of an instruction
|
||||
/// executed by <c>Microsoft.Iris.Markup.Interpreter</c>.
|
||||
/// </summary>
|
||||
public void LogInterpreterOpCode(object context, InterpreterEntry entry);
|
||||
void LogInterpreterOpCode(object context, InterpreterEntry entry);
|
||||
|
||||
/// <summary>
|
||||
/// Logs the string representation of a dispatcher step.
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
public void LogDispatcher(string message);
|
||||
void LogDispatcher(string message);
|
||||
}
|
||||
|
||||
@@ -1,24 +1,35 @@
|
||||
using Microsoft.Iris.Debug.Data;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Text;
|
||||
|
||||
namespace Microsoft.Iris.Debug.SystemNet;
|
||||
|
||||
public class NetDebuggerClient : IDebuggerClient, IDisposable
|
||||
{
|
||||
private readonly Socket _socket;
|
||||
private readonly ConcurrentQueue<byte[]> _outQueue = new();
|
||||
private readonly IFormatter _formatter;
|
||||
private InterpreterCommand _uibCommand = InterpreterCommand.Continue;
|
||||
|
||||
public Uri ConnectionUri { get; }
|
||||
|
||||
private readonly Socket _socket;
|
||||
private readonly Queue<byte[]> _queue;
|
||||
private readonly IFormatter _formatter;
|
||||
public InterpreterCommand DebuggerCommand
|
||||
{
|
||||
get => _uibCommand;
|
||||
set
|
||||
{
|
||||
var data = new[] { (byte)value };
|
||||
QueueDebuggerMessage(new(0, DebuggerMessageType.InterpreterCommand, data));
|
||||
_uibCommand = value;
|
||||
}
|
||||
}
|
||||
|
||||
public event EventHandler<InterpreterEntry> InterpreterStep;
|
||||
public event Action<string> DispatcherStep;
|
||||
public event Action<InterpreterCommand> InterpreterStateChanged;
|
||||
|
||||
public NetDebuggerClient(string connectionUri) : this(new Uri(connectionUri))
|
||||
{
|
||||
@@ -30,18 +41,31 @@ public class NetDebuggerClient : IDebuggerClient, IDisposable
|
||||
_socket = new(SocketType.Stream, ProtocolType.Tcp);
|
||||
_formatter = DebugRemoting.CreateBsonFormatter();
|
||||
|
||||
System.Threading.Thread connectThread = new(ConnectLoop);
|
||||
System.Threading.Thread connectThread = new(ConnectLoop) { IsBackground = true };
|
||||
connectThread.Start();
|
||||
}
|
||||
|
||||
public void Dispose() => _socket.Dispose();
|
||||
public void Dispose()
|
||||
{
|
||||
if (_socket != null)
|
||||
{
|
||||
if (_socket.Connected)
|
||||
_socket.Disconnect(false);
|
||||
_socket.Close();
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateBreakpoint(Breakpoint breakpoint)
|
||||
{
|
||||
QueueDebuggerMessage(new(0, DebuggerMessageType.UpdateBreakpoint, breakpoint.Serialize(_formatter)));
|
||||
}
|
||||
|
||||
private void QueueDebuggerMessage(DebuggerMessageFrame frame)
|
||||
{
|
||||
_queue.Enqueue(frame.ToBytes());
|
||||
_outQueue.Enqueue(frame.ToBytes());
|
||||
}
|
||||
|
||||
private void MessageRecieveLoop()
|
||||
private void MessageReceiveLoop()
|
||||
{
|
||||
while (_socket.Connected)
|
||||
{
|
||||
@@ -52,11 +76,8 @@ public class NetDebuggerClient : IDebuggerClient, IDisposable
|
||||
switch (frame.Type)
|
||||
{
|
||||
case DebuggerMessageType.InterpreterOpCode:
|
||||
{
|
||||
using MemoryStream stream = new(frame.Data);
|
||||
var entry = (InterpreterEntry)_formatter.Deserialize(stream);
|
||||
InterpreterStep?.Invoke(this, entry);
|
||||
}
|
||||
var entry = frame.DeserializeData<InterpreterEntry>(_formatter);
|
||||
InterpreterStep?.Invoke(this, entry);
|
||||
break;
|
||||
|
||||
case DebuggerMessageType.DispatcherStep:
|
||||
@@ -64,6 +85,11 @@ public class NetDebuggerClient : IDebuggerClient, IDisposable
|
||||
DispatcherStep?.Invoke(message);
|
||||
break;
|
||||
|
||||
case DebuggerMessageType.InterpreterCommand:
|
||||
_uibCommand = (InterpreterCommand)frame.Data[0];
|
||||
InterpreterStateChanged?.Invoke(_uibCommand);
|
||||
break;
|
||||
|
||||
default:
|
||||
Trace.WriteLine(TraceCategory.MarkupDebug, "Recieved unknown debugger message of type '{0}'.", frame.Type);
|
||||
break;
|
||||
@@ -71,6 +97,18 @@ public class NetDebuggerClient : IDebuggerClient, IDisposable
|
||||
}
|
||||
}
|
||||
|
||||
private void MessageSendLoop()
|
||||
{
|
||||
while (_socket.Connected)
|
||||
{
|
||||
byte[] frameBytes;
|
||||
while (!_outQueue.TryDequeue(out frameBytes)) ;
|
||||
|
||||
_socket.Send(BitConverter.GetBytes(frameBytes.Length));
|
||||
_socket.Send(frameBytes);
|
||||
}
|
||||
}
|
||||
|
||||
private void ConnectLoop()
|
||||
{
|
||||
while (!_socket.Connected)
|
||||
@@ -83,7 +121,9 @@ public class NetDebuggerClient : IDebuggerClient, IDisposable
|
||||
catch { }
|
||||
}
|
||||
|
||||
System.Threading.Thread receiveThread = new(MessageRecieveLoop);
|
||||
System.Threading.Thread receiveThread = new(MessageReceiveLoop) { IsBackground = true };
|
||||
System.Threading.Thread sendThread = new(MessageSendLoop) { IsBackground = true };
|
||||
receiveThread.Start();
|
||||
sendThread.Start();
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
using Microsoft.Iris.Debug.Data;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.IO;
|
||||
using System.Net.Sockets;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
@@ -11,13 +10,25 @@ internal class NetDebuggerServer : IDebuggerServer, IDisposable
|
||||
{
|
||||
public static IDebuggerServer Current { get; private set; }
|
||||
|
||||
public Uri ConnectionUri { get; }
|
||||
|
||||
private readonly ConcurrentQueue<byte[]> _outQueue = new();
|
||||
private readonly TcpListener _listener;
|
||||
private readonly IFormatter _formatter;
|
||||
private Socket _socket;
|
||||
private bool _disposed = false;
|
||||
private InterpreterCommand _uibCommand = InterpreterCommand.Continue;
|
||||
|
||||
public Uri ConnectionUri { get; }
|
||||
|
||||
public InterpreterCommand DebuggerCommand
|
||||
{
|
||||
get => _uibCommand;
|
||||
set
|
||||
{
|
||||
var data = new[] { (byte)value };
|
||||
QueueDebuggerMessage(new(0, DebuggerMessageType.InterpreterCommand, data));
|
||||
_uibCommand = value;
|
||||
}
|
||||
}
|
||||
|
||||
public NetDebuggerServer(string connectionUri) : this(new Uri(connectionUri))
|
||||
{
|
||||
@@ -32,7 +43,7 @@ internal class NetDebuggerServer : IDebuggerServer, IDisposable
|
||||
|
||||
_formatter = DebugRemoting.CreateBsonFormatter();
|
||||
|
||||
System.Threading.Thread connectThread = new(ConnectLoop);
|
||||
System.Threading.Thread connectThread = new(ConnectLoop) { IsBackground = true };
|
||||
connectThread.Start();
|
||||
|
||||
Current = this;
|
||||
@@ -40,10 +51,7 @@ internal class NetDebuggerServer : IDebuggerServer, IDisposable
|
||||
|
||||
public void LogInterpreterOpCode(object context, InterpreterEntry entry)
|
||||
{
|
||||
using MemoryStream entryStream = new();
|
||||
_formatter.Serialize(entryStream, entry);
|
||||
|
||||
QueueDebuggerMessage(new(0, DebuggerMessageType.InterpreterOpCode, entryStream.ToArray()));
|
||||
QueueDebuggerMessage(new(0, DebuggerMessageType.InterpreterOpCode, entry.Serialize(_formatter)));
|
||||
}
|
||||
|
||||
public void LogDispatcher(string message)
|
||||
@@ -66,16 +74,28 @@ internal class NetDebuggerServer : IDebuggerServer, IDisposable
|
||||
_outQueue.Enqueue(frame.ToBytes());
|
||||
}
|
||||
|
||||
private void MessageRecieveLoop()
|
||||
private void MessageReceiveLoop()
|
||||
{
|
||||
while (_socket.Connected)
|
||||
{
|
||||
DebuggerMessageFrame frame;
|
||||
while ((frame = DebugRemoting.ReceiveDebuggerMessage(_socket)) == null)
|
||||
;
|
||||
if (!_socket.Connected) return;
|
||||
|
||||
switch (frame.Type)
|
||||
{
|
||||
case DebuggerMessageType.UpdateBreakpoint:
|
||||
var breakpoint = frame.DeserializeData<Breakpoint>(_formatter);
|
||||
if (breakpoint.Enabled)
|
||||
Application.DebugSettings.Breakpoints.Add(breakpoint);
|
||||
else
|
||||
Application.DebugSettings.Breakpoints.Remove(breakpoint);
|
||||
break;
|
||||
|
||||
case DebuggerMessageType.InterpreterCommand:
|
||||
_uibCommand = (InterpreterCommand)frame.Data[0];
|
||||
break;
|
||||
|
||||
default:
|
||||
Trace.WriteLine(TraceCategory.MarkupDebug, "Recieved unknown debugger message of type '{0}'.", frame.Type);
|
||||
break;
|
||||
@@ -90,8 +110,12 @@ internal class NetDebuggerServer : IDebuggerServer, IDisposable
|
||||
byte[] frameBytes;
|
||||
while (!_outQueue.TryDequeue(out frameBytes)) ;
|
||||
|
||||
_socket.Send(BitConverter.GetBytes(frameBytes.Length));
|
||||
_socket.Send(frameBytes);
|
||||
try
|
||||
{
|
||||
_socket.Send(BitConverter.GetBytes(frameBytes.Length));
|
||||
_socket.Send(frameBytes);
|
||||
}
|
||||
catch (SocketException) { }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,8 +126,8 @@ internal class NetDebuggerServer : IDebuggerServer, IDisposable
|
||||
|
||||
_socket = _listener.AcceptSocket();
|
||||
|
||||
System.Threading.Thread receiveThread = new(MessageRecieveLoop);
|
||||
System.Threading.Thread sendThread = new(MessageSendLoop);
|
||||
System.Threading.Thread receiveThread = new(MessageReceiveLoop) { IsBackground = true };
|
||||
System.Threading.Thread sendThread = new(MessageSendLoop) { IsBackground = true };
|
||||
receiveThread.Start();
|
||||
sendThread.Start();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user