/* Copyright (c) 1999 Microsoft Corporation Module Name: WorkerThread.cpp Abstract: Implementation of CWorkerThread class */ #include "common.h" #include "WorkerThread.h" /////////////////////////////////////////////////////////////////////////////// // // CWorkerThread::Initialize // // create the thread // /////////////////////////////////////////////////////////////////////////////// HRESULT CWorkerThread::Initialize() { // // if the thread is already initialized // if ( (NULL != m_hThreadHandle) && (0 != m_nThreadID) ) { LogError("CWorkerThread::Initialize() thread is already running"); return E_UNEXPECTED; } // // start the thread // m_hThreadHandle = CreateThread(NULL, // security 0, // stack ThreadFunction, // thread function 0, // thread parameter 0, // flags &m_nThreadID); // // thread creation failed. log a message and return an error // if (NULL == m_hThreadHandle) { LogError("CWorkerThread::Initialize() " "failed to start the worker thread"); return E_FAIL; } // // thread created. log thread id. // LogMessage("CWorkerThread::Initialize() succeeded. thread id [0x%lx]", m_nThreadID); return S_OK; } /////////////////////////////////////////////////////////////////////////////// // // CWorkerThread::Shutdown // // exit the thread and close thread handle // /////////////////////////////////////////////////////////////////////////////// HRESULT CWorkerThread::Shutdown() { LogError("CWorkerThread::Shutdown() entered"); // // if the thread is running, post quit message and wait for thread to exit // if (NULL != m_hThreadHandle) { // // let the thread know it's time to go home // PostMessage(WM_QUIT, NULL, NULL); // // wait for the thread to disappear // DWORD rc = WaitForSingleObject(m_hThreadHandle, INFINITE); // // close thread handle // CloseHandle(m_hThreadHandle); m_hThreadHandle = NULL; m_nThreadID = 0; if (rc != WAIT_OBJECT_0) { LogError("CWorkerThread::Shutdown() " "Failed waiting for thread to shutdown"); return E_FAIL; } else { LogMessage("CWorkerThread::Shutdown() finished"); return S_OK; } } else { // // thread was not running // LogError("CWorkerThread::Shutdown() thread is not running"); return E_FAIL; } } /////////////////////////////////////////////////////////////////////////////// // // CWorkerThread::~CWorkerThread // // log a message and fire assert in the thread is still running // /////////////////////////////////////////////////////////////////////////////// CWorkerThread::~CWorkerThread() { LogError("CWorkerThread::~CWorkerThread() entered"); // // the thread should not be running at this point -- the app should have // called Shutdown() // if (NULL != m_hThreadHandle) { LogError("CWorkerThread::~CWorkerThread thread [%ld] is still running", m_nThreadID); } _ASSERTE(NULL == m_hThreadHandle); LogError("CWorkerThread::~CWorkerThread() finished"); } /////////////////////////////////////////////////////////////////////////////// // // CWorkerThread::PostMessage // // posts a message to the thread // /////////////////////////////////////////////////////////////////////////////// BOOL CWorkerThread::PostMessage( UINT Msg, // message to post WPARAM wParam, // first message parameter LPARAM lParam // second message parameter ) { BOOL bReturn = FALSE; if (NULL != m_hThreadHandle) { // // the thread is running, post the message // bReturn = PostThreadMessage(m_nThreadID, Msg, wParam, lParam); } return bReturn; } /////////////////////////////////////////////////////////////////////////////// // // CWorkerThread::ThreadFunction // // // thread function. receives messages posted to the thread. Forwards TAPI // messages to TAPI event handler. Exits on WM_QUIT. // /////////////////////////////////////////////////////////////////////////////// unsigned long _stdcall CWorkerThread::ThreadFunction(void *) { LogMessage("CWorkerThread::ThreadFunction() starting"); CoInitializeEx(NULL, COINIT_MULTITHREADED); // // force creation of message queue // MSG msg; // // keep retrieving messages until we fail or get WM_QUIT // while (GetMessage(&msg, NULL, 0, 0)) { switch (msg.message) { case WM_PRIVATETAPIEVENT: { // // get event from the message // TAPI_EVENT TapiEvent = (TAPI_EVENT)msg.wParam; IDispatch *pEvent = (IDispatch*)msg.lParam; // // pass event to the event handler // OnTapiEvent(TapiEvent, pEvent); pEvent = NULL; // // do not check the error code from event handler - // there is not much we can do here anyway. // // // Note: pEvent is released by OnTapiEvent, so we should not // use it after OnTapiEvent returns // } break; default: // // we are not interested in any other messages // break; } } // while (GetMessage()) CoUninitialize(); LogMessage("CWorkerThread::ThreadFunction() exiting"); return 0; } // CWorkerThread::ThreadFunction