/* Copyright 2003,2004 GSMK mbH, Berlin * All Rights Reserved * * $Header$ * * * this is a templated and thread safe fifo * */ #ifndef __NHQUEUE_H__ #include #include "debug.h" template class NHQueue { public: NHQueue(int size); ~NHQueue(); void Reset(); bool Add(M msg); bool GetWait(M& msg); bool GetNoWait(M& msg); int Size() const; bool IsFull() const; bool IsEmpty() const; void DumpState(); private: std::vector m_list; int m_maxSize; int m_head; int m_tail; int m_size; int m_overflows; int m_errors; int m_total_in; int m_total_out; int m_total_empty; HANDLE m_hEvent; CRITICAL_SECTION m_lock; bool Get(M& msg, bool bWait); }; template NHQueue::NHQueue(int size) { m_list.resize(size); m_maxSize= size; InitializeCriticalSection(&m_lock); m_hEvent= CreateEvent(NULL, FALSE, FALSE, NULL); if (m_hEvent==INVALID_HANDLE_VALUE) error("ERROR creating Event\n"); Reset(); } template void NHQueue::Reset() { m_size=0; m_head=0; m_tail=0; m_overflows= 0; m_errors= 0; m_total_in= 0; m_total_out= 0; m_total_empty= 0; } template NHQueue::~NHQueue() { DeleteCriticalSection(&m_lock); if (!CloseHandle(m_hEvent)) error("ERROR closing Event handle\n"); } // this is called from within callbacks: don't use anything // else but criticalsection and event calls. template bool NHQueue::Add(M msg) { bool bRes; EnterCriticalSection(&m_lock); m_total_in++; if (!IsFull()) { m_list[m_tail]= msg; if (++m_tail == m_maxSize) m_tail= 0; ++m_size; if (!SetEvent(m_hEvent)) m_errors++; bRes= true; } else { m_overflows++; bRes= false; } LeaveCriticalSection(&m_lock); return bRes; } template bool NHQueue::Get(M& msg, bool bWait) { if (!IsEmpty() || (bWait && WaitForSingleObject(m_hEvent, INFINITE)==WAIT_OBJECT_0)) { if (!ResetEvent(m_hEvent)) m_errors++; EnterCriticalSection(&m_lock); msg= m_list[m_head]; if (++m_head==m_maxSize) m_head= 0; --m_size; LeaveCriticalSection(&m_lock); m_total_out++; return true; } if (bWait) m_errors++; m_total_empty++; return false; } template bool NHQueue::GetWait(M& msg) { return Get(msg, true); } template bool NHQueue::GetNoWait(M& msg) { return Get(msg, false); } template int NHQueue::Size() const { return m_size; } template bool NHQueue::IsFull() const { return (m_size==m_maxSize); } template bool NHQueue::IsEmpty() const { return (m_size==0); } template void NHQueue::DumpState() { debug("queue::state size=%d max=%d head=%d tail=%d overflow=%d errors=%d in=%d out=%d empty=%d\n", m_size, m_maxSize, m_head, m_tail, m_overflows, m_errors, m_total_in, m_total_out, m_total_empty); } #define __NHQUEUE_H__ #endif