/************************************************************************************************ Copyright (c) 2001 Microsoft Corporation File Name: ThdPool.cpp Abstract: Implementation of the thread pool (CThreadPool class) Notes: History: 08/01/2001 Created by Hao Yu (haoyu) ************************************************************************************************/ #include #include #include #include // The common thread in the thread pool DWORD WINAPI ThreadProc(LPVOID lpParameter) { ASSERT(NULL != lpParameter); DWORD dwBytesRcvd=0; DWORD Flags=0; PIO_CONTEXT pIoContext=NULL; LPOVERLAPPED pOverlapped=NULL; HANDLE hCompPort=lpParameter; HRESULT hr=CoInitializeEx(NULL, COINIT_MULTITHREADED); if(FAILED(hr)) { g_EventLogger.LogEvent(LOGTYPE_ERR_CRITICAL, EVENT_POP3_COM_INIT_FAIL); ExitProcess(hr); } while(1) { GetQueuedCompletionStatus(hCompPort, &dwBytesRcvd, (PULONG_PTR)(&pIoContext), &pOverlapped, INFINITE); //We don't care about return value //since we use the failure case to clean up the IO Context if(NULL == pIoContext || SERVICE_STOP_PENDING == g_dwServerStatus) { // This is a shutdown signal break; } g_PerfCounters.DecPerfCntr(e_gcFreeThreadCnt); pIoContext->m_pCallBack((PULONG_PTR)pIoContext, pOverlapped, dwBytesRcvd); g_PerfCounters.IncPerfCntr(e_gcFreeThreadCnt); } g_PerfCounters.DecPerfCntr(e_gcFreeThreadCnt); CoUninitialize(); return 0; } CThreadPool::CThreadPool() { InitializeCriticalSection(&m_csInitGuard); m_hIOCompPort = NULL; m_phTdArray = NULL; m_dwTdCount = 0; m_bInit = FALSE; } CThreadPool::~CThreadPool() { if(m_bInit) { Uninitialize(); } DeleteCriticalSection(&m_csInitGuard); } // Job done in this function: // 1) Calculate the number of threads need to be created, // dwThreadPerProcessor * number of processors of the machine // 2) Create the IO Completion port // 3) Create threads BOOL CThreadPool::Initialize(DWORD dwThreadPerProcessor) { int i; BOOL bRtVal=TRUE; SYSTEM_INFO SystemInfo; EnterCriticalSection(&m_csInitGuard); if(!m_bInit) { //Get the number of processors of the machine GetSystemInfo(&SystemInfo); if( dwThreadPerProcessor == 0 || dwThreadPerProcessor > MAX_THREAD_PER_PROCESSOR ) { dwThreadPerProcessor = 1; } m_dwTdCount = SystemInfo.dwNumberOfProcessors * dwThreadPerProcessor; // Create the IO Completion Port m_hIOCompPort = CreateIoCompletionPort ( INVALID_HANDLE_VALUE, NULL, NULL, m_dwTdCount); if (NULL == m_hIOCompPort) { g_EventLogger.LogEvent(LOGTYPE_ERR_CRITICAL, POP3SVR_FAIL_TO_CREATE_IO_COMP_PORT, GetLastError()); goto EXIT; } m_phTdArray=new HANDLE[m_dwTdCount]; if( NULL == m_phTdArray) { g_EventLogger.LogEvent(LOGTYPE_ERR_CRITICAL, POP3SVR_NOT_ENOUGH_MEMORY); goto EXIT; } // Create the threads for (i=0;im_hAsyncIO), m_hIOCompPort, (ULONG_PTR)pIoContext, m_dwTdCount)); }