|
|
using System;
|
|
|
using System.Collections.Generic;
|
|
|
using System.Threading;
|
|
|
|
|
|
namespace Implab.Diagnostics {
|
|
|
/// <summary>
|
|
|
/// Trace context is bound to the specific thread, each thread has it's own ThreadContext.
|
|
|
/// </summary>
|
|
|
/// <remarks>
|
|
|
/// ThreadContext manages relations between logical operations and threads.
|
|
|
/// </remarks>
|
|
|
public class TraceContext {
|
|
|
|
|
|
[ThreadStatic]
|
|
|
static TraceContext _instance;
|
|
|
|
|
|
OperationContext m_current = OperationContext.EMPTY;
|
|
|
readonly Stack<OperationContext> m_stack = new Stack<OperationContext>();
|
|
|
readonly int m_threadId;
|
|
|
|
|
|
public static TraceContext Instance {
|
|
|
get {
|
|
|
if (_instance == null)
|
|
|
_instance = new TraceContext();
|
|
|
return _instance;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
public TraceContext() {
|
|
|
m_threadId = Thread.CurrentThread.ManagedThreadId;
|
|
|
}
|
|
|
|
|
|
public int ThreadId {
|
|
|
get { return m_threadId; }
|
|
|
}
|
|
|
|
|
|
public LogicalOperation CurrentOperation {
|
|
|
get {
|
|
|
return m_current.CurrentOperation;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
public void EnterLogicalOperation(LogicalOperation operation, bool takeOwnership) {
|
|
|
//var prev = CurrentOperation;
|
|
|
//LogChannel<TraceEvent>.Default.LogEvent(new TraceEvent(takeOwnership ? TraceEventType.Attach : TraceEventType.Enter, String.Format("{0} -> {1}",prev.Name, operation.Name)));
|
|
|
m_stack.Push(m_current);
|
|
|
m_current = new OperationContext(operation, takeOwnership);
|
|
|
}
|
|
|
|
|
|
public void StartLogicalOperation(string name) {
|
|
|
LogChannel<TraceEvent>.Default.LogEvent(new TraceEvent(TraceEventType.OperationStarted, name));
|
|
|
m_current.BeginLogicalOperation(name);
|
|
|
}
|
|
|
|
|
|
public void StartLogicalOperation() {
|
|
|
StartLogicalOperation(String.Empty);
|
|
|
}
|
|
|
|
|
|
public LogicalOperation EndLogicalOperation() {
|
|
|
return m_current.EndLogicalOperation();
|
|
|
}
|
|
|
|
|
|
public LogicalOperation DetachLogicalOperation() {
|
|
|
var prev = m_current.DetachLogicalOperation();
|
|
|
//LogChannel<TraceEvent>.Default.LogEvent(new TraceEvent(TraceEventType.Detach, String.Format("{0} -> {1}",prev.Name, CurrentOperation.Name)));
|
|
|
return prev;
|
|
|
}
|
|
|
|
|
|
public void Leave() {
|
|
|
if (m_stack.Count > 0) {
|
|
|
m_current.Leave();
|
|
|
//var prev = CurrentOperation;
|
|
|
m_current = m_stack.Pop();
|
|
|
//LogChannel<TraceEvent>.Default.LogEvent(new TraceEvent(TraceEventType.Leave, String.Format("{0} -> {1}", prev.Name, CurrentOperation.Name)));
|
|
|
} else {
|
|
|
TraceLog.TraceWarning("Attempt to leave the last operation context");
|
|
|
m_current = OperationContext.EMPTY;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|