///////////////////////////////////////////////////////////////////////////// // // Copyright (c) 1997-1999 Microsoft Corporation // // Module Name: // WorkThrd.h // // Abstract: // Definition of the CWorkerThread class. // // Implementation File: // WorkThrd.cpp // // Author: // David Potter (davidp) November 17, 1997 // // Revision History: // // Notes: // ///////////////////////////////////////////////////////////////////////////// #ifndef __WORKTHRD_H_ #define __WORKTHRD_H_ ///////////////////////////////////////////////////////////////////////////// // Forward Class Declarations ///////////////////////////////////////////////////////////////////////////// class CWorkerThread; ///////////////////////////////////////////////////////////////////////////// // External Class Declarations ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// // Include Files ///////////////////////////////////////////////////////////////////////////// #ifndef _EXCOPER_H_ #include "ExcOper.h" // for CNTException #endif ///////////////////////////////////////////////////////////////////////////// // Type Definitions ///////////////////////////////////////////////////////////////////////////// // Worker thread function codes. enum { WTF_EXIT = -1, // Ask the thread to exit. WTF_NONE = 0, // No function. WTF_USER = 1000 // User functions start here. }; ///////////////////////////////////////////////////////////////////////////// //++ // // class CWorkerThread // // Purpose: // This class provides a means of calling functions in a worker thread // and allowing a UI application to still respond to Windows messages. // The user of this class owns the input and output data pointed to // by this class. // // Inheritance: // CWorkerThread // //-- ///////////////////////////////////////////////////////////////////////////// class CWorkerThread { public: // // Construction and destruction. // // Default constructor CWorkerThread( void ) : m_hThread( NULL ) , m_hMutex( NULL ) , m_hInputEvent( NULL ) , m_hOutputEvent( NULL) , m_idThread( 0 ) , m_bThreadExiting( FALSE ) , m_nFunction( WTF_NONE ) , m_pvParam1( NULL ) , m_pvParam2( NULL ) , m_dwOutputStatus( ERROR_SUCCESS ) , m_nte( ERROR_SUCCESS ) , m_pfnOldWndProc( NULL ) , m_hCurrentCursor( NULL ) { } //*** CWorkerThread() // Destructor ~CWorkerThread( void ) { ATLASSERT( m_nFunction == WTF_NONE ); ATLASSERT( m_pvParam1 == NULL ); ATLASSERT( m_pvParam2 == NULL ); Cleanup(); ATLASSERT( m_bThreadExiting ); } //*** ~CWorkerThread() // Create the thread DWORD CreateThread( void ); // Ask the thread to exit void QuitThread( IN HWND hwnd = NULL ) { ATLASSERT( ! m_bThreadExiting ); CWaitCursor wc; CallThreadFunction( hwnd, WTF_EXIT, NULL, NULL ); } //*** QuitThread() // Call a function supported by the thread DWORD CallThreadFunction( IN HWND hwnd, IN LONG nFunction, IN OUT PVOID pvParam1 = NULL, IN OUT PVOID pvParam2 = NULL ); // Wait for the thread to exit DWORD WaitForThreadToExit( IN HWND hwnd ); public: // // Accessor functions. // // Get the thread handle operator HANDLE( void ) const { return m_hThread; } //*** operator HANDLE() // Get the thread handle HANDLE HThreadHandle( void ) const { return m_hThread; } //*** HThreadHandle() // Get the thread ID operator DWORD( void ) const { return m_idThread; } //*** operator DWORD() // Get exception information resulting from a thread function call CNTException & Nte( void ) { return m_nte; } //*** Nte() // Get exception information resulting from a thread function call operator CNTException *( void ) { return &m_nte; } //*** operator CNTException *() protected: // // Synchronization data. // HANDLE m_hThread; // Handle for the thread. HANDLE m_hMutex; // Handle for the mutex used to call a // function in the thread. HANDLE m_hInputEvent; // Handle for the event used by the calling // thread to signal the worker thread that // there is work to do. HANDLE m_hOutputEvent; // Handle for the event used by the worker // thread to signal the calling thread // that the work has been completed. UINT m_idThread; // ID for the thread. BOOL m_bThreadExiting; // Determine if thread is exiting or not. // // Data used as input or produced by the thread. // LONG m_nFunction; // ID of the function to perform. PVOID m_pvParam1; // Parameter 1 with function-specific data. PVOID m_pvParam2; // Parameter 2 with function-specific data. DWORD m_dwOutputStatus; // Status returned from the function. CNTException m_nte; // Exception information from the function. // // Data and methods for handling WM_SETCURSOR messages. // WNDPROC m_pfnOldWndProc; // Old window procedure for the parent window. HCURSOR m_hCurrentCursor; // Cursor to display while waiting for thread call to complete. // Window procedure for subclassing the parent window static LRESULT WINAPI S_ParentWndProc( IN HWND hwnd, IN UINT uMsg, IN WPARAM wParam, IN LPARAM lParam ); // // Thread worker functions. // // Static thread procedure static UINT __stdcall S_ThreadProc( IN OUT LPVOID pvThis ); // Thread function handler virtual DWORD ThreadFunctionHandler( IN LONG nFunction, IN OUT PVOID pvParam1, IN OUT PVOID pvParam2 ) = 0; // // Helper functions. // // Prepare a window to wait for a thread operation void PrepareWindowToWait( IN HWND hwnd ); // Cleanup a window after waiting for a thread operation void CleanupWindowAfterWait( IN HWND hwnd ); // Cleanup objects virtual void Cleanup( void ) { if ( m_hThread != NULL ) { if ( ! m_bThreadExiting && (m_nFunction != WTF_EXIT) ) { QuitThread(); } // if: thread hasn't exited yet ATLTRACE( _T("CWorkerThread::Cleanup() - Closing thread handle\n") ); CloseHandle( m_hThread ); m_hThread = NULL; } // if: thread created if ( m_hMutex != NULL ) { ATLTRACE( _T("CWorkerThread::Cleanup() - Closing mutex handle\n") ); CloseHandle( m_hMutex ); m_hMutex = NULL; } // if: mutex created if ( m_hInputEvent != NULL ) { ATLTRACE( _T("CWorkerThread::Cleanup() - Closing input event handle\n") ); CloseHandle( m_hInputEvent ); m_hInputEvent = NULL; } // if: input event created if ( m_hOutputEvent != NULL ) { ATLTRACE( _T("CWorkerThread::Cleanup() - Closing output event handle\n") ); CloseHandle( m_hOutputEvent ); m_hOutputEvent = NULL; } // if: output event created } //*** Cleanup() }; // class CWorkerThread ///////////////////////////////////////////////////////////////////////////// #endif // __WORKTHRD_H_