Created
March 10, 2012 00:09
-
-
Save shanewfx/2009416 to your computer and use it in GitHub Desktop.
Loop Queue
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// CQueue | |
// | |
// Implements a simple Queue ADT. The queue contains a finite number of | |
// objects, access to which is controlled by a semaphore. The semaphore | |
// is created with an initial count (N). Each time an object is added | |
// a call to WaitForSingleObject is made on the semaphore's handle. When | |
// this function returns a slot has been reserved in the queue for the new | |
// object. If no slots are available the function blocks until one becomes | |
// available. Each time an object is removed from the queue ReleaseSemaphore | |
// is called on the semaphore's handle, thus freeing a slot in the queue. | |
// If no objects are present in the queue the function blocks until an | |
// object has been added. | |
#define DEFAULT_QUEUESIZE 2 | |
template <class T> class CQueue { | |
private: | |
HANDLE hSemPut; // Semaphore controlling queue "putting" | |
HANDLE hSemGet; // Semaphore controlling queue "getting" | |
CRITICAL_SECTION CritSect; // Thread seriallization | |
int nMax; // Max objects allowed in queue | |
int iNextPut; // Array index of next "PutMsg" | |
int iNextGet; // Array index of next "GetMsg" | |
T *QueueObjects; // Array of objects (ptr's to void) | |
void Initialize(int n) { | |
iNextPut = iNextGet = 0; | |
nMax = n; | |
InitializeCriticalSection(&CritSect); | |
hSemPut = CreateSemaphore(NULL, n, n, NULL); | |
hSemGet = CreateSemaphore(NULL, 0, n, NULL); | |
QueueObjects = new T[n]; | |
} | |
public: | |
CQueue(int n) { | |
Initialize(n); | |
} | |
CQueue() { | |
Initialize(DEFAULT_QUEUESIZE); | |
} | |
~CQueue() { | |
delete [] QueueObjects; | |
DeleteCriticalSection(&CritSect); | |
CloseHandle(hSemPut); | |
CloseHandle(hSemGet); | |
} | |
T GetQueueObject() { | |
int iSlot; | |
T Object; | |
LONG lPrevious; | |
// Wait for someone to put something on our queue, returns straight | |
// away is there is already an object on the queue. | |
// | |
WaitForSingleObject(hSemGet, INFINITE); | |
EnterCriticalSection(&CritSect); | |
iSlot = iNextGet++ % nMax; | |
Object = QueueObjects[iSlot]; | |
LeaveCriticalSection(&CritSect); | |
// Release anyone waiting to put an object onto our queue as there | |
// is now space available in the queue. | |
// | |
ReleaseSemaphore(hSemPut, 1L, &lPrevious); | |
return Object; | |
} | |
void PutQueueObject(T Object) { | |
int iSlot; | |
LONG lPrevious; | |
// Wait for someone to get something from our queue, returns straight | |
// away is there is already an empty slot on the queue. | |
// | |
WaitForSingleObject(hSemPut, INFINITE); | |
EnterCriticalSection(&CritSect); | |
iSlot = iNextPut++ % nMax; | |
QueueObjects[iSlot] = Object; | |
LeaveCriticalSection(&CritSect); | |
// Release anyone waiting to remove an object from our queue as there | |
// is now an object available to be removed. | |
// | |
ReleaseSemaphore(hSemGet, 1L, &lPrevious); | |
} | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment