I have not figured out how/if instances of this WorkerThread can deallocate themselves after being cleared from the ThreadPool. Until I resolve this I guess I have to send a message telling the worker function to break its loop and clean up. But I have a KillThread method just in case.
Any comments or suggestions for this code?
#pragma once
class WorkerThread
{
public:
WorkerThread(DWORD i) : m_Quit(false), m_Shutdown(false)
{
InitializeCriticalSection(&Request_Mutex);
InitializeCriticalSection(&Completed_Mutex);
hThread = CreateThread(NULL, 0, WorkerThread::ThreadRoutine, this, NULL, NULL);
}
~WorkerThread(void)
{
if(hThread)
{
CloseHandle(hThread);
}
DeleteCriticalSection(&Request_Mutex);
DeleteCriticalSection(&Completed_Mutex);
}
void TickMain(); //Only called by Client code
bool SendRequest(std::shared_ptr<InstructionBase> spNewRequest);
bool GetCompleted(std::shared_ptr<InstructionBase> &spNewRequest);
void KillWorkerThread();
protected:
bool m_Quit, m_Shutdown;
virtual void ThreadFunction() = 0;
//Functions called by ThreadFunction()
void ThreadGet();
void ThreadSend();
std::queue<std::shared_ptr<InstructionBase> > Thread_Requests;
std::vector<std::shared_ptr<InstructionBase> > Thread_Completed;
private:
//Functions called by TickMain()
void MainSend();
void MainGet();
//Main side containers
std::vector<std::shared_ptr<InstructionBase> > Main_Requests;
std::queue<std::shared_ptr<InstructionBase> > Main_Completed;
//In between containers and mutex
CRITICAL_SECTION Request_Mutex;
CRITICAL_SECTION Completed_Mutex;
std::vector<std::shared_ptr<InstructionBase> > Mutex_Requests;
std::vector<std::shared_ptr<InstructionBase> > Mutex_Completed;
//Thread system
HANDLE hThread;
static DWORD WINAPI ThreadRoutine(LPVOID param)
{
static_cast<WorkerThread*>(param)->ThreadFunction();
return 0;
}
};
class DerivedA : public WorkerThread
{
public:
DerivedA(DWORD i) : WorkerThread(i)
{
}
private:
void ThreadFunction()
{
//Thread variables
while(!m_Quit){
void ThreadGet();
if(Thread_Requests.empty()){
Sleep(1);
} else {
std::shared_ptr<InstructionBase> spNewRequest = Thread_Requests.front();
Thread_Requests.pop();
//Do work on spNewRequest
Thread_Completed.push_back(spNewRequest);
}
void ThreadSend();
}
}
};
#include "WorkerThread.h"
void WorkerThread::KillWorkerThread()
{
m_Quit = true;
m_Shutdown = true;
if(hThread != NULL)
{
Sleep(50);
TerminateThread(hThread, 0);
hThread = NULL;
}
}
bool WorkerThread::SendRequest(std::shared_ptr<InstructionBase> spNewRequest)
{
if(m_Quit || m_Shutdown || hThread == NULL){
return false;
}
Main_Requests.push_back(spNewRequest);
return true;
}
bool WorkerThread::GetCompleted(std::shared_ptr<InstructionBase> &spNewRequest)
{
if(Main_Completed.empty()){
return false;
}
spNewRequest = Main_Completed.front();
Main_Completed.pop();
return true;
}
void WorkerThread::TickMain()
{
MainSend();
MainGet();
}
void WorkerThread::MainSend()
{
if(Main_Requests.empty()){
return;
}
if(TryEnterCriticalSection(&Request_Mutex)){
for(size_t i=0;i<Main_Requests.size();i++){
Mutex_Requests.push_back(Main_Requests[i]);
}
LeaveCriticalSection(&Request_Mutex);
Main_Requests.clear();
}
}
void WorkerThread::MainGet()
{
if(TryEnterCriticalSection(&Completed_Mutex)){
for(size_t i=0;i<Mutex_Completed.size();i++){
Main_Completed.push(Mutex_Completed[i]);
}
Mutex_Completed.clear();
LeaveCriticalSection(&Completed_Mutex);
}
}
void WorkerThread::ThreadSend()
{
if(Thread_Completed.empty()){
return;
}
if(TryEnterCriticalSection(&Completed_Mutex)){
for(size_t i=0;i<Thread_Completed.size();i++){
Mutex_Completed.push_back(Thread_Completed[i]);
}
LeaveCriticalSection(&Completed_Mutex);
Thread_Completed.clear();
}
}
void WorkerThread::ThreadGet()
{
if(TryEnterCriticalSection(&Request_Mutex)){
for(size_t i=0;i<Mutex_Requests.size();i++){
Thread_Requests.push(Mutex_Requests[i]);
}
Mutex_Requests.clear();
LeaveCriticalSection(&Request_Mutex);
}
}