Cosmos/source2/Debug/Cosmos.Debug.VSDebugEngine/Engine.Impl/OperationThread.cs
kudzu_cp 34c3a187a9
2009-05-28 14:26:33 +00:00

163 lines
4.9 KiB
C#

using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
namespace Cosmos.Debug.VSDebugEngine
{
public delegate void Operation();
// This object represents the debugger poll thread to the managed portion of the engine. It allows the engine to perform
// operations on the poll thread. This is required because the Win32 debugging API requires thread affinity for several operations.
public class WorkerThread : IDisposable
{
readonly ManualResetEvent m_opSet;
readonly ManualResetEvent m_opComplete;
readonly Operation m_quitOperation;
Operation m_op;
bool m_fSyncOp;
Exception m_opException;
//DebuggedProcess m_debuggedProcess;
public WorkerThread()
{
m_opSet = new ManualResetEvent(false);
m_opComplete = new ManualResetEvent(true);
m_quitOperation = new Operation(delegate() { });
Thread thread = new Thread(new ThreadStart(ThreadFunc));
thread.Start();
}
//public void SetDebugProcess(DebuggedProcess debuggedProcess)
//{
// System.Diagnostics.System.Diagnostics.Debug.Assert(m_debuggedProcess == null);
// m_debuggedProcess = debuggedProcess;
//}
public void RunOperation(Operation op)
{
if (op == null)
throw new ArgumentNullException();
SetOperationInternal(op, true);
}
public void RunOperationAsync(Operation op)
{
if (op == null)
throw new ArgumentNullException();
SetOperationInternal(op, false);
}
public void Close()
{
RunOperationAsync(m_quitOperation);
}
internal void SetOperationInternal(Operation op, bool fSyncOp)
{
while (true)
{
m_opComplete.WaitOne();
if (TrySetOperationInternal(op, fSyncOp))
{
return;
}
}
}
bool TrySetOperationInternal(Operation op, bool fSyncOp)
{
lock(this)
{
if (m_op == null)
{
m_op = op;
m_fSyncOp = fSyncOp;
m_opException = null;
m_opComplete.Reset();
m_opSet.Set();
if (fSyncOp)
{
m_opComplete.WaitOne();
if (m_opException != null)
{
throw m_opException;
}
}
return true;
}
else if (m_op == m_quitOperation)
{
if (op == m_quitOperation)
{
return true; // we are already closed
}
else
{
// Can't try to run something after calling Close
throw new InvalidOperationException();
}
}
}
return false;
}
// Thread routine for the poll loop. It handles calls coming in from the debug engine as well as polling for debug events.
private void ThreadFunc()
{
bool fQuit = false;
while (!fQuit)
{
//if ((m_debuggedProcess != null) && (m_debuggedProcess.IsPumpingDebugEvents))
{
//m_debuggedProcess.WaitForAndDispatchDebugEvent(ResumeEventPumpFlags.ResumeWithExceptionHandled);
}
// If the other thread is dispatching a command, execute it now.
bool fReceivedCommand = m_opSet.WaitOne(new TimeSpan(0, 0, 0, 0, 100), false);
if (fReceivedCommand)
{
if (m_fSyncOp)
{
try
{
m_op();
}
catch (Exception opException)
{
m_opException = opException;
}
}
else
{
m_op();
}
fQuit = (m_op == m_quitOperation);
if (!fQuit)
{
m_op = null;
}
m_opComplete.Set();
m_opSet.Reset();
}
}
}
void IDisposable.Dispose()
{
Close();
}
}
}