#ifndef __SAFEQUEUE_H__ #define __SAFEQUEUE_H__ #ifndef _WINDOWS_ #include #endif #include using namespace std; template < class T > class CSafeQueue { public: // Constructor(s) and Destructor CSafeQueue() { InitQueue(); } virtual ~CSafeQueue() { if ( GetQueueFlag() != NULL ) DeleteQueue(); } // Public operations // Adds element to queue void AddTail( const T& element ) { LockQueue(); m_queue.push_back( new T(element) ); UnlockQueue(); // Set modified flag SetQueueFlag(); } void AddTail( const T* pElement ) { LockQueue(); m_queue.push_back( pElement ); UnlockQueue(); // Set modified flag SetQueueFlag(); } // Removes element from front T* RemoveFront() { static T *pElement = NULL; // Initialize to Null first if ( !IsEmpty() ) { LockQueue(); pElement = (T*) m_queue.front(); // Delete the first element m_queue.erase(m_queue.begin()); UnlockQueue(); } // Set modified flag SetQueueFlag(); return pElement; } // Returns queue size const int GetSize() const { return( m_queue.size() ); } // Returns boolean value, true if queue is empty const bool IsEmpty() const { return( m_queue.empty() ); } // Sets the queue flag appropriately, // depending upon current queue size void SetQueueFlag() { if ( GetSize() != 0 ) SetEvent( m_hQueueFull ); else ResetEvent( m_hQueueFull ); } // Returns queue handle HANDLE GetQueueFlag() const { return m_hQueueFull; } // Initializes the queue void InitQueue() { InitializeCriticalSection( &m_criticalSection ); SECURITY_ATTRIBUTES sAttrib; sAttrib.nLength = sizeof( SECURITY_ATTRIBUTES ); sAttrib.lpSecurityDescriptor = NULL; sAttrib.bInheritHandle = TRUE; // Create queue event indicator m_hQueueFull = CreateEvent( &sAttrib, TRUE, FALSE, NULL ); } // Clears queue contents void Clear() { LockQueue(); m_queue.clear(); UnlockQueue(); // Set modified flag SetQueueFlag(); } // Checks if any thread is using the queue object // Use this in a multi-threaded environment before calling DeleteQueue const bool CanDelete() const { if ( WaitForSingleObject( m_hQueueFull, 0 ) == WAIT_OBJECT_0 ) return false; // State of m_hQueueFull is no longer signaled.. return true; } // Delete queue, and free resources const int DeleteQueue() { static int nStat = -1; Clear(); // Clear contents of queue // Okay for freeing resources DeleteCriticalSection( &m_criticalSection ); if ( CloseHandle( m_hQueueFull ) ) { m_hQueueFull = NULL; nStat = 0; } return nStat; } private: // Private operations // Locks the current queue object void LockQueue() { EnterCriticalSection( &m_criticalSection ); } // Unlocks current queue void UnlockQueue() { LeaveCriticalSection( &m_criticalSection ); } private: // Private attributes ( data members ) CRITICAL_SECTION m_criticalSection; HANDLE m_hQueueFull; //deque < T, allocator< T > > m_queue; deque < T* > m_queue; }; #endif //__SAFEQUEUE_H__