Listing 1

#include "TraceBuffer.h"

CTraceBuffer::CTraceBuffer() :
    m_nInsertPos(-1),
    m_nRetrievePos(-1)
{
    memset(m_buffer, 0, sizeof(m_buffer));
    m_hNumFreeEntriesSemaphore = 
         CreateSemaphore(NULL, TRACE_BUFFER_SIZE, TRACE_BUFFER_SIZE, NULL);
    m_hNumItemsToCollectSemaphore = 
        CreateSemaphore(NULL, 0, TRACE_BUFFER_SIZE, NULL);
}
CTraceBuffer::~CTraceBuffer()
{
    CloseHandle(m_hNumFreeEntriesSemaphore);
    CloseHandle(m_hNumItemsToCollectSemaphore);
}
void CTraceBuffer::Insert(TraceLevel_En nTraceLevel, LPCTSTR lpszTrace)
{
    long  nPrevCount = 0;
    long  nInsertPos = 0;
    DWORD dwTimeout = (nTraceLevel == eTraceLevelAbort ? INFINITE : 0);
    // wait until there is a free position in the buffer
    if (WAIT_OBJECT_0 != 
            WaitForSingleObject(m_hNumFreeEntriesSemaphore, dwTimeout))
        return;
    nInsertPos = InterlockedIncrement(&m_nInsertPos);
    TraceInfo& buffEntry = m_buffer[nInsertPos%TRACE_BUFFER_SIZE];
    // insert the trace into the buff
    strcpy(buffEntry.szTrace, lpszTrace);
    buffEntry.nLevel = nTraceLevel;
    buffEntry.dwThreadId = GetCurrentThreadId();
    // after inserting new item incerement num of items to collect from buffer
    ReleaseSemaphore(m_hNumItemsToCollectSemaphore, 1, &nPrevCount);
}
long CTraceBuffer::Retrieve(TraceInfo& traceInfo)
{
    long nPrevNumFreeEntries = 0;
    long  nRetrievePos = 0;
    // wait until there is at least one item to collect from buffer
    if (WAIT_OBJECT_0 != 
             WaitForSingleObject(m_hNumItemsToCollectSemaphore, 10000))
        return 0;
    nRetrievePos = InterlockedIncrement(&m_nRetrievePos);
    // copy the trace info from the buffer 
    // don't use traceInfo = 
                m_buffer[nRetrievePos%TRACE_BUFFER_SIZE] - its slower!
    strcpy(traceInfo.szTrace, 
                m_buffer[nRetrievePos%TRACE_BUFFER_SIZE].szTrace);
    traceInfo.nLevel = m_buffer[nRetrievePos%TRACE_BUFFER_SIZE].nLevel;
    traceInfo.dwThreadId = m_buffer[nRetrievePos%TRACE_BUFFER_SIZE].dwThreadId;
    // after retrieving an item incerement num of free entries in buffer
    ReleaseSemaphore(m_hNumFreeEntriesSemaphore, 1, &nPrevNumFreeEntries);
    // return number traces left in buffer
    return (TRACE_BUFFER_SIZE - (nPrevNumFreeEntries+1));
}