#pragma once // // The CDataQueue class implements a thread-safe queue data-structure // with the ability of notifying the addition of data into the queue // via a WIN32 EVENT object that is accessible through the "GetWaitHandle" // method. Use "Enqueue" to enqueue data and "Dequeue" to dequeue // data (duh!). The class assumes that the methods "Enqueue" and "Dequeue" // can be invoked on different threads. // // It keeps the event signalled while there is data to be read from the // queue. "Dequeue" returns NULL when the queue is empty. Being a queue // of course it operates on a FIFO basis. // template<typename T> class CDataQueue : public CAutoCriticalSectionLockable<CDataQueue<T> > { protected: HANDLE m_hEvent; list<T> m_Queue; bool m_bEnabled; public: CDataQueue( bool bEnabled ) { m_hEvent = NULL; m_bEnabled = false; SetEnabled( bEnabled ); } CDataQueue(void) { m_hEvent = NULL; m_bEnabled = false; SetEnabled( false ); } ~CDataQueue(void) { SetEnabled( false ); } HANDLE GetWaitHandle() const { return m_hEvent; } void Clear() { // // clear the queue // CObjectLock lock( this ); m_Queue.clear(); // // reset the event object // if( m_hEvent != NULL ) ResetEvent( m_hEvent ); } const list<T>& GetQueue() const { return m_Queue; } void SetEnabled( bool bEnabled ) { CObjectLock lock( this ); // // if this is a redundant call then do nothing // if( m_bEnabled == bEnabled ) return; // // if we are being enabled, then create the event // object; and if we are disabled then delete the // event object and reinitialize the queue // if( m_bEnabled == false ) { // // create a manual reset event // m_hEvent = CreateEvent( NULL, TRUE, FALSE, NULL ); } else { CloseHandle( m_hEvent ); m_hEvent = NULL; m_Queue.clear(); } m_bEnabled = bEnabled; } bool GetEnabled() const { return m_bEnabled; } bool Enqueue( const T& Data ) { // // enqueue only if we are in the enabled // state // if( GetEnabled() == false ) return false; m_cs.Lock(); m_Queue.push_back( Data ); m_cs.Unlock(); // // notify listeners that there's data to be read // SetEvent( m_hEvent ); return true; } bool DequeueAll( list<T>& dataList ) { // // dequeue only if we are in the enabled // state // if( GetEnabled() == false ) return false; CObjectLock lock( this ); // // if the queue is empty then return false // if( m_Queue.size() == 0 ) return false; // // copy all of our data into "dataList" // dataList.assign(m_Queue.begin(), m_Queue.end()); m_Queue.clear(); ResetEvent( m_hEvent ); return true; } bool Dequeue( T& data ) { // // dequeue only if we are in the enabled // state // if( GetEnabled() == false ) return false; CObjectLock lock( this ); // // if the queue is empty then return false // if( m_Queue.size() == 0 ) return false; data = m_Queue.front(); m_Queue.pop_front(); // // if the queue is empty then reset the event // if( m_Queue.size() == 0 ) { ResetEvent( m_hEvent ); } return true; } };
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.
This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)