namespace Implab.Diagnostics { struct OperationContext { public readonly static OperationContext EMPTY = new OperationContext(LogicalOperation.EMPTY, false); LogicalOperation m_initial; LogicalOperation m_current; bool m_ownership; public OperationContext(LogicalOperation operation, bool ownership) { Safe.ArgumentNotNull(operation, "operation"); m_initial = operation; m_current = operation; m_ownership = ownership; } public LogicalOperation CurrentOperation { get { return m_current; } } public void BeginLogicalOperation(string name) { m_current = new LogicalOperation(name, m_current); } public LogicalOperation DetachLogicalOperation() { var detached = m_current; if (m_current != LogicalOperation.EMPTY) { if (m_current != m_initial) m_current = m_current.Parent; else if (m_ownership) m_current = LogicalOperation.EMPTY; else { TraceLog.TraceWarning("DetachLogicalOperation can't be applied in the current context"); detached = LogicalOperation.EMPTY; } } else { TraceLog.TraceWarning("DetachLogicalOperation can't be applied in the current context"); } return detached; } public LogicalOperation EndLogicalOperation() { var current = m_current; if (m_current != LogicalOperation.EMPTY && (m_current != m_initial || m_ownership)) { m_current = m_current.Parent; if (current == m_initial) { // we have complete the owned operation m_initial = m_current; m_ownership = false; } } else { TraceLog.TraceWarning("EndLogicalOperation can't be applied in the current context"); } return current; } public void Leave() { if ((m_ownership && m_current != LogicalOperation.EMPTY) || (!m_ownership && m_current != m_initial) ) TraceLog.TraceWarning("Trying to leave unfinished logical operation {0}", m_current.Name); } } }