Tweets

Generic Thread Object

his code implements a generic thread object. I have derived from this class to produce thread pools in multithreaded servers.

This interface assumes that the user is interested in working at the thread/process level of detail. Abstractions could be used if necessary.

Note that this is a console application [uses fprintf(stderr,...)] - the message mechanism could be easily abstracted but doing so would have violated the goal of simplicity, until such time as that abstraction is necessary.

Compatibility/System Requirements

This code was compiled with VC7 on Windows 2000 and Windows XP systems.

Code

// Thread Tools
// Copyright (c) 2004, 2005 Robin Eric Fredericksen
// -- All rights reserved.

//==================================================
// The interfaces
//==================================================

//==================================================
// use this for auto scope protection for threading
//==================================================
class CScopeProtector

{

protected
:
CRITICAL_SECTION & m_roCS;

public
:
CScopeProtector(CRITICAL_SECTION & _roCS)
:
m_roCS(_roCS)
{

EnterCriticalSection(&m_roCS);
}


virtual
~CScopeProtector()
{

LeaveCriticalSection(&m_roCS);
}
};



//==================================================
class CTaskThread

{

public
:

enum

{

INITIALIZED,
RELEASED,

WAITING,
ASSIGNED,
RUNNING,
DEAD
}
threadstate;

protected
:

// debugging
HANDLE m_hThreadHandle;
DWORD m_dwThreadID;

// for blocking and waiting for work

HANDLE m_hGateKeeper;

// for keeping track of where we are, for others to query
DWORD m_dwThreadState;

public
:

CTaskThread(void);

virtual
~CTaskThread();

DWORD GetThreadState(void) { return(m_dwThreadState); }

bool
InitSuccess(void) { return( m_hThreadHandle && m_hGateKeeper ); }

// override this function to implement your work
virtual DWORD VirtualCallbackFunction(void);

// this is the function that will be spawned
static int __cdecl TaskThread( void * _pvMyThisPointer );

typedef
void( __cdecl *pFNStartAddress )( void * );

HANDLE StartThread(void);

// opens gate for thread to try to do work
void ReleaseThread(void);

};



//==================================================
// The implementation
//==================================================
#include <process.h>


//==================================================
CTaskThread::CTaskThread(void)
{

m_dwThreadID = 0;

m_hThreadHandle = 0;
m_hGateKeeper = 0;

m_dwThreadState = DEAD;

m_hGateKeeper = CreateEvent(

NULL, // default security
TRUE, // manually reset
FALSE, // start nonsignaled
NULL // not named

);

if
( m_hGateKeeper )
{

StartThread();
}
}


//==================================================
CTaskThread::~CTaskThread()
{

if
( m_hGateKeeper ) CloseHandle(m_hGateKeeper);

m_dwThreadState = DEAD;
}


//==================================================
void CTaskThread::ReleaseThread(void)
{


m_dwThreadState = RELEASED;
SetEvent(m_hGateKeeper);
}


//==================================================
HANDLE CTaskThread::StartThread(void)
{


// we are required to have a function with a particular signature
// here, so we us an intermediary so we maintain our class-yness. ;)
m_hThreadHandle = (HANDLE)// returns threadID
_beginthread(
(
pFNStartAddress)TaskThread,
NULL, // default thread stack

this
);

return
( m_hThreadHandle );
}



//==================================================
// this is the function that will be spawned
//==================================================


int __cdecl CTaskThread::TaskThread( void * _pvMyThisPointer )
{

if
( !_pvMyThisPointer ) return(-1);

CTaskThread * pMe = (CTaskThread*)_pvMyThisPointer;

pMe->m_dwThreadID = GetCurrentThreadId();

DWORD dwResult = 0;
// go to a waiting state
pMe->m_dwThreadState = WAITING;

while
(WAIT_OBJECT_0 == WaitForSingleObject(pMe->m_hGateKeeper, INFINITE) )
{


// indicate that we are running
pMe->m_dwThreadState = RUNNING;

// call the virtual function to do the work
dwResult = pMe->VirtualCallbackFunction();

// go back to a waiting state
ResetEvent(pMe->m_hGateKeeper);
pMe->m_dwThreadState = WAITING;
}


pMe->m_dwThreadState = DEAD;
return
(dwResult);
}


//==================================================
DWORD CTaskThread::VirtualCallbackFunction(void)
{

// this is the function to be over-ridden
// could make it pure virtual...
Sleep(1000);

return
(0);
};