176 lines
3.8 KiB
C++
176 lines
3.8 KiB
C++
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Module : Common
|
|
// Description : Generic Thread Base class
|
|
// Uses Win32 SEH
|
|
//
|
|
// File : genthread.h
|
|
// Author : kulor
|
|
// Date : 05/18/2000
|
|
//
|
|
// History :
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
#pragma once
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// class CGenThread
|
|
//
|
|
// Usage : 1) Derive from this class and implement the Run method.
|
|
// 2) Use the IsStopRequested appropriately.
|
|
//
|
|
//
|
|
typedef class CGenThread {
|
|
|
|
public:
|
|
CGenThread (bool fStart = false) {
|
|
|
|
m_hGenThread = NULL;
|
|
m_dwThreadId = 0;
|
|
m_hGenStopEvent = ::CreateEvent (
|
|
NULL,
|
|
true,
|
|
false,
|
|
NULL
|
|
);
|
|
if ( fStart ) {
|
|
Start ();
|
|
}
|
|
}
|
|
|
|
virtual ~CGenThread () {
|
|
CleanupThread ();
|
|
}
|
|
|
|
DWORD GetThreadId ( void ) { return m_dwThreadId ; }
|
|
|
|
DWORD Start ( DWORD dwCreateFlags = 0 ) {
|
|
|
|
DWORD dwRet = FALSE;
|
|
|
|
if ( !fOkToRun () || IsValidThread () )
|
|
return FALSE;
|
|
|
|
// de-signal the event
|
|
::ResetEvent ( m_hGenStopEvent );
|
|
|
|
m_hGenThread = ::CreateThread (
|
|
NULL,
|
|
0,
|
|
GenThreadProc,
|
|
reinterpret_cast <void*>(this),
|
|
0,
|
|
&m_dwThreadId
|
|
);
|
|
dwRet = ( m_hGenThread ? 0 : GetLastError() );
|
|
|
|
return dwRet;
|
|
}
|
|
|
|
DWORD Stop ( void ) {
|
|
|
|
if ( IsValidThread () == FALSE )
|
|
return FALSE;
|
|
|
|
// signal the thread
|
|
::SetEvent ( m_hGenStopEvent );
|
|
|
|
// now wait for it to stop
|
|
DWORD dwRet = ::WaitForSingleObject ( m_hGenThread , INFINITE );
|
|
|
|
CleanupThread ();
|
|
|
|
return dwRet;
|
|
}
|
|
|
|
DWORD Pause ( void ) {
|
|
|
|
if ( IsValidThread() == FALSE )
|
|
return FALSE;
|
|
|
|
::SuspendThread ( m_hGenThread );
|
|
return GetLastError ();
|
|
}
|
|
|
|
DWORD Resume ( void ) {
|
|
|
|
if ( IsValidThread() == FALSE )
|
|
return FALSE;
|
|
|
|
::ResumeThread ( m_hGenThread );
|
|
return GetLastError ();
|
|
}
|
|
|
|
bool IsStopRequested ( void ) {
|
|
bool fVal = false;
|
|
|
|
fVal = ( ::WaitForSingleObject ( m_hGenStopEvent, 0 ) == WAIT_OBJECT_0 );
|
|
|
|
return (fVal);
|
|
}
|
|
|
|
virtual DWORD Run ( void ) = 0 ;
|
|
|
|
bool IsValidThread ( void ) {
|
|
return ( m_hGenThread != NULL );
|
|
}
|
|
|
|
protected:
|
|
|
|
void CleanupThread ( void ) {
|
|
|
|
m_dwThreadId = 0;
|
|
|
|
if ( m_hGenStopEvent ) {
|
|
::CloseHandle ( m_hGenStopEvent );
|
|
m_hGenStopEvent = NULL;
|
|
}
|
|
|
|
if ( m_hGenThread ) {
|
|
::CloseHandle ( m_hGenThread );
|
|
m_hGenThread = NULL;
|
|
}
|
|
}
|
|
|
|
virtual bool fOkToRun( void ) {
|
|
return ( m_hGenStopEvent != NULL );
|
|
}
|
|
|
|
static DWORD WINAPI GenThreadProc(
|
|
LPVOID lpParameter
|
|
)
|
|
{
|
|
|
|
CGenThread *pGenThread = reinterpret_cast<CGenThread*> (lpParameter);
|
|
DWORD dwRet = 0;
|
|
|
|
if ( pGenThread ) {
|
|
__try {
|
|
|
|
dwRet = pGenThread->Run ();
|
|
}
|
|
|
|
__except ( EXCEPTION_EXECUTE_HANDLER, 1 ) {
|
|
|
|
// wireup crash info
|
|
}
|
|
|
|
{
|
|
|
|
pGenThread->CleanupThread ();
|
|
}
|
|
}
|
|
|
|
return dwRet;
|
|
}
|
|
|
|
protected:
|
|
HANDLE m_hGenStopEvent;
|
|
HANDLE m_hGenThread;
|
|
DWORD m_dwThreadId;
|
|
|
|
} CGenThread, GENTHREAD, *PGENTHREAD;
|
|
|