// File: ActiveQueue.h
#if !defined(__ActiveThread_H)
#define __ActiveThread_H
#if !defined(_DEQUE_)
#include <deque>
#endif
#if !defined(_QUEUE_)
#include <queue>
#endif
#if !defined(__THREAD_H)
#include "thread.h"
#endif
// Exception class
class FailedToCreateSemaphore
{
};
class FailedToCreateThread
{
};
// We inherit protected from Thread to prevent a user from calling
// create. We do this instead of changing protection on Create from
// public to private, because Borland 5.0 has a problem with
// changing protection on members in base classes.
template <class T>
class ActiveQueue : protected Thread
{
public:
ActiveQueue(DWORD dwParam = 0,DWORD dwCreationFlags = 0);
virtual ~ActiveQueue();
virtual void Add(const T &data);
// Redefine operator HANDLE so an ActiveQueue can be turned into
// a HANDLE for syncronization, and other thread related matters
operator HANDLE();
protected:
virtual bool Initialize();
virtual bool HandleData(T &data) = 0;
private:
HANDLE hQueueEntries;
CRITICAL_SECTION criticalSection;
// We specify the deque as default container, because
// Borland 5.0 has a limited support for default templates
std::queue<T,std::deque<T> > dataQueue;
virtual UINT ThreadFunction(DWORD);
ActiveQueue(ActiveQueue&); //prevent copying - make ctor private
operator =(ActiveQueue&); //prevent assignment - ctor private
};
template <class T>
ActiveQueue<T> :: ActiveQueue(DWORD dwParam,DWORD dwCreationFlags)
{
hQueueEntries = CreateSemaphore(NULL,0,MAXLONG,NULL);
if (hQueueEntries == NULL)
throw FailedToCreateSemaphore();
// Create the thread
if (Create(dwParam,dwCreationFlags) == FALSE)
{
CloseHandle(hQueueEntries);
throw FailedToCreateThread();
}
InitializeCriticalSection(&criticalSection);
}
template <class T>
ActiveQueue<T> :: ~ActiveQueue()
{
CloseHandle(hQueueEntries);
DeleteCriticalSection(&criticalSection);
}
template <class T>
void ActiveQueue<T> :: Add(const T &data)
{
EnterCriticalSection(&criticalSection);
dataQueue.push(data);
LeaveCriticalSection(&criticalSection);
ReleaseSemaphore(hQueueEntries,1,NULL);
}
template <class T>
ActiveQueue<T> :: operator HANDLE()
{
return Thread::operator HANDLE();
}
template <class T>
bool ActiveQueue<T> :: Initialize()
{
return true;
}
template <class T>
UINT ActiveQueue<T> :: ThreadFunction(DWORD)
{
T data;
if (Initialize() == false)
return 0;
while (true)
{
WaitForSingleObject(hQueueEntries,INFINITE);
EnterCriticalSection(&criticalSection);
data = dataQueue.front();
dataQueue.pop();
LeaveCriticalSection(&criticalSection);
if (HandleData(data) == false)
break;
}
return 0;
}
#endif
//End of File