Description
STL provides a basic sequence known as deque (a double-ended queue). A deque is a sequence optimized so that operations at both ends are about as efficient as for a list, whereas subscripting approaches the efficiency of a vector. A deque is used where additions and deletions take place "at the ends".
Purpose
If this deque is to be accessed in different threads, some form of synchronization of the queue access would be necessary, for example, providing locking and unlocking mechanism.
In view of this, it seems necessary and good to have a class that can be as flexible as to allow usage in multi-threaded environment as well. A wrapper class for deque - provides the same efficiency but provides extra feature of thread synchronization.
For instance, we could model the following class:
template < class T >
class CSafeQueue
{
public:
// Constructor(s) and Destructor
CSafeQueue()
{
InitQueue(); // Initializes critical section and creates
// queue event indicator handle
}
virtual ~CSafeQueue()
{
if ( GetQueueFlag() != NULL )
DeleteQueue(); // Deletes contents and critical section
// before finally closing the event indicator handle.
}
// Public operations
// Adds element to queue
void AddTail( const T* pElement )
{
LockQueue();
m_queue.push_back( *pElement );
UnlockQueue();
// Set modified flag
SetQueueFlag();
}
...
...
private:
...
// Locks the current queue object
void LockQueue()
{
EnterCriticalSection( &m_criticalSection );
}
// Unlocks current queue
void UnlockQueue()
{
LeaveCriticalSection( &m_criticalSection );
}
...
...
}
Thus, what we have is an efficient queue template class that can store any data type sequence to implement FIFO and yet have the features of thread synchronization.
Example Usage:
CSafeQueue< int > intQueue; // queue of integer values
intQueue.AddTail( 1 );
intQueue.AddTail( 2 );
intQueue.AddTail( 3 );
while( !intQueue.IsEmpty() )
{
int *pInt = (int*)intQueue.RemoveFront();
if ( pInt != NULL )
cout << "Removing " << *pInt << endl;
}
// Delete queue
intQueue.DeleteQueue();
In the case of multi-threaded system, before deleting, one could call functions like CanDelete() first before calling DeleteQueue(). CanDelete() checks if the queue handle is being hold by any thread. If no threads hold this, it will have a non-signaled state and the queue handle can also be closed at the time of deleting queue.
Also, in similar fashion, we can write thread-safe wrapper class for vector.
View code here