//*************************************************************************** // // Copyright (c) 2000-2001 Microsoft Corporation // // thrdpool.h // // rajeshr 01-Jan-01 Created. // // Thread Pool for handling ISAPI requests // The main reason we require a thread pool is that we need to do COM initialization on // our own threads // //*************************************************************************** #include CThreadPool::CThreadPool() { m_oMonitorThread = NULL; m_cNumberOfThreads = m_cNumberOfActiveThreads = 0; m_pWorkerThreads = NULL; m_oSemaphore = NULL; m_bShutDown = false; } CThreadPool::~CThreadPool() { } HRESULT CThreadPool::Initialize(LONG cNumberOfThreads, LONG cTaskQueueLength) { HRESULT hr = E_FAIL; // Initialize the circular queue if(SUCCEEDED(hr = m_oQueue.Initialize(cTaskQueueLength))) { // Create the semaphore if(m_oSemaphore = CreateSemaphore(NULL, 0, cNumberOfThreads, NULL)) { // Create the array of handles of the worker threads if(m_pWorkerThreads = new HANDLE[cNumberOfThreads]) { // Create the worker threads themselves for(int i=0; im_bShutDown) { // Decrement the count of active threads InterlockedDecrement(&(pPool->m_cNumberOfActiveThreads)); break; } // Wait for the next task WaitForSingleObject(pPool->m_oSemaphore, INFINITE); CTask *pNextTask = NULL; if(pNextTask = (pPool->m_oQueue).RemoveTask()) { pNextTask->Execute(); // Destroy the task object delete pNextTask; } else { // The Semaphore was set without a task being in the queue // This special condition is created when we want the Thread Pool to shutdown // Decrement the count of active threads InterlockedDecrement(&(pPool->m_cNumberOfActiveThreads)); break; } } CoUninitialize(); } ExitThread(0); return 0; } ///////////////////////////////////////// // Code for the circular queue of tasks //////////////////////////////////////// CTask :: CTask(LPEXTENSION_CONTROL_BLOCK pECB) { m_pECB = pECB; } CTask :: ~CTask() {} void CTask :: Execute() { // Figure out what sort of request we are dealing with HTTPTransport httpTransport (m_pECB, HTTP_WMI_SOAP_ACTION); if (httpTransport.IsPostOrMPost ()) { // Create ourselves an HTTP endpoint bound to our specific action if (httpTransport.IsValidEncapsulation()) { SOAPActor soapActor (httpTransport); soapActor.Act(); } } else if (httpTransport.IsGet ()) { // A WMI object GET ObjectRetriever objectRetriever (httpTransport); objectRetriever.Fetch (); } else { // Anything else is not supported by us httpTransport.SendStatus("501 Not Implemented", false); } // Inform IIS that we are finally done with the request m_pECB->ServerSupportFunction( m_pECB->ConnID, HSE_REQ_DONE_WITH_SESSION, NULL, NULL, NULL ); } CTaskQueue::CTaskQueue() { m_ppTasks = NULL; m_cMaxTasks = 0; m_iHead = m_iTail = -1; } CTaskQueue::~CTaskQueue() { EnterCriticalSection(&m_csQueueProtector); // Kill all the pending tasks in the queue // By this time all the worker threads should have been terminated CTask *pNextTask = NULL; while(pNextTask = RemoveTask()) { // Inform IIS that we are finally done with the request pNextTask->m_pECB->ServerSupportFunction( pNextTask->m_pECB->ConnID, HSE_REQ_DONE_WITH_SESSION, NULL, NULL, NULL ); delete pNextTask; } delete [] m_ppTasks; LeaveCriticalSection(&m_csQueueProtector); DeleteCriticalSection(&m_csQueueProtector); } HRESULT CTaskQueue::Initialize(LONG cMaxTasks) { if(cMaxTasks < 2) return S_FALSE; InitializeCriticalSection(&m_csQueueProtector); HRESULT hr = S_OK; if(m_ppTasks = new CTask * [cMaxTasks]) { for(int i=0; i