///////////////////////////////////////////////////////////////////////////// // // 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 (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 (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;