void CThreadPools::CreateThreadPools(int nThreadCount) { BOOL bRet = FALSE; InitializeThreadpoolEnvironment(&m_CallBackEnviron); // Create a custom, dedicated thread pool m_pPool = CreateThreadpool(NULL); if (NULL==m_pPool) { CloseThreadPools(); } m_nRollback = 1; // pool creation succeeded // The thread pool is made persistent simply by setting // both the minimum and maximum threads to 1. SetThreadpoolThreadMaximum(m_pPool, nThreadCount); bRet = SetThreadpoolThreadMinimum(m_pPool, 1); if (FALSE==bRet) { CloseThreadPools(); } //Create a cleanup group for this thread pool m_pCleanupGroup = CreateThreadpoolCleanupGroup(); if (NULL==m_pCleanupGroup) { CloseThreadPools(); } m_nRollback = 2; // Cleanup group creation succeeded // Associate the callback environment with our thread pool. SetThreadpoolCallbackPool(&m_CallBackEnviron, m_pPool); // Associate the cleanup group with our thread pool. // Objects created with the same callback environment // as the cleanup group become members of the cleanup group. SetThreadpoolCallbackCleanupGroup(&m_CallBackEnviron, m_pCleanupGroup, NULL); m_nRollback = 3; // Creation of work succeeded }
bool test_new_thread_pool() {//success is true, failure is false int sockErr; WSADATA lpWSAData={0}; sockErr=WSAStartup(0x202, &lpWSAData); sListen=WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED); if(INVALID_SOCKET==sListen){ DebugBreak(); } GUID GuidDisconnectEx = WSAID_DISCONNECTEX; DWORD dwBytes; WSAIoctl(sListen, SIO_GET_EXTENSION_FUNCTION_POINTER, &GuidDisconnectEx, sizeof (GuidDisconnectEx), &DisconnectEx, sizeof (DisconnectEx), &dwBytes, NULL, NULL); InitializeThreadpoolEnvironment(&tEnvrion); pMainPool=CreateThreadpool(NULL); pCleanup=CreateThreadpoolCleanupGroup(); SetThreadpoolCallbackCleanupGroup(&tEnvrion, pCleanup, 0); SetThreadpoolCallbackPool(&tEnvrion, pMainPool); pListen=CreateThreadpoolIo((HANDLE)sListen, acceptingIoThreadProc, 0, &tEnvrion); sockaddr_in service={0}; service.sin_family=AF_INET; service.sin_port=htons(8080); sockErr=bind(sListen, (SOCKADDR *) &service, sizeof(service)); if(SOCKET_ERROR==sockErr){ DebugBreak(); } sockErr=listen(sListen, SOMAXCONN); if(SOCKET_ERROR==sockErr){ DebugBreak(); } for(int i=0; i<numSockets; i++){ ntpAddAcceptSocket(sListen); } OutputDebugString(TEXT("CloseThreadpoolCleanupGroupMembers waiting\n")); SleepEx(INFINITE, TRUE); CloseThreadpoolCleanupGroupMembers(pCleanup, FALSE, NULL); OutputDebugString(TEXT("CloseThreadpoolCleanupGroupMembers done\n")); return false; }
UINT32 HlprThreadPoolDataPopulate(_Inout_ THREADPOOL_DATA* pThreadPoolData, _In_ const PTP_CLEANUP_GROUP_CANCEL_CALLBACK pGroupCancelFn) { ASSERT(pThreadPoolData); UINT32 status = NO_ERROR; InitializeThreadpoolEnvironment(&(pThreadPoolData->callbackEnvironment)); pThreadPoolData->pThreadPool = CreateThreadpool(0); if(pThreadPoolData->pThreadPool == 0) { status = GetLastError(); HlprLogError(L"HlprThreadPoolDataPopulate : CreateThreadPool() [status: %#x]", status); HLPR_BAIL; } pThreadPoolData->pCleanupGroup = CreateThreadpoolCleanupGroup(); if(pThreadPoolData->pCleanupGroup == 0) { status = GetLastError(); HlprLogError(L"HlprThreadPoolDataPopulate : CreateThreadPool() [status: %#x]", status); HLPR_BAIL; } SetThreadpoolCallbackPool(&(pThreadPoolData->callbackEnvironment), pThreadPoolData->pThreadPool); SetThreadpoolCallbackCleanupGroup(&(pThreadPoolData->callbackEnvironment), pThreadPoolData->pCleanupGroup, pGroupCancelFn); HLPR_BAIL_LABEL: if(status != NO_ERROR) HlprThreadPoolDataPurge(pThreadPoolData); return status; }
__declspec(noinline) bool benchmark_ntp_fs_stat() { TP_CALLBACK_ENVIRON env; InitializeThreadpoolEnvironment(&env); PTP_POOL pool{nullptr}; pool = CreateThreadpool(nullptr); SetThreadpoolThreadMaximum(pool, 48); SetThreadpoolThreadMinimum(pool, 12); PTP_CLEANUP_GROUP group = CreateThreadpoolCleanupGroup(); SetThreadpoolCallbackPool(&env, pool); SetThreadpoolCallbackCleanupGroup(&env, group, nullptr); PTP_WORK work_fs_stat = CreateThreadpoolWork(WorkCallback_fs_stat, nullptr, &env); SubmitThreadpoolWork(work_fs_stat); WaitForThreadpoolWorkCallbacks(work_fs_stat, false); CloseThreadpoolWork(work_fs_stat); CloseThreadpool(pool); return false; }
bool Server::Create(short port, int maxPostAccept) { assert(maxPostAccept > 0); m_MaxPostAccept = maxPostAccept; // Create Client Work Thread Env for using cleaning group. We need this for shutting down // properly. InitializeThreadpoolEnvironment(&m_ClientTPENV); m_ClientTPCLEAN = CreateThreadpoolCleanupGroup(); if (m_ClientTPCLEAN == NULL) { ERROR_CODE(GetLastError(), "Could not create client cleaning group."); return false; } SetThreadpoolCallbackCleanupGroup(&m_ClientTPENV, m_ClientTPCLEAN, NULL); // Create Listen Socket m_listenSocket = Network::CreateSocket(true, port); if (m_listenSocket == INVALID_SOCKET) { return false; } // Make the address re-usable to re-run the same server instantly. bool reuseAddr = true; if (setsockopt(m_listenSocket, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast<const char*>(&reuseAddr), sizeof(reuseAddr)) == SOCKET_ERROR) { ERROR_CODE(WSAGetLastError(), "setsockopt() failed with SO_REUSEADDR."); Destroy(); return false; } // Create & Start ThreaddPool for socket IO m_pTPIO = CreateThreadpoolIo(reinterpret_cast<HANDLE>(m_listenSocket), Server::IoCompletionCallback, NULL, NULL); if (m_pTPIO == NULL) { ERROR_CODE(WSAGetLastError(), "Could not assign the listen socket to the IOCP handle."); Destroy(); return false; } // Start listening StartThreadpoolIo(m_pTPIO); if (listen(m_listenSocket, SOMAXCONN) == SOCKET_ERROR) { ERROR_CODE(WSAGetLastError(), "listen() failed."); return false; } // Create critical sections for m_Clients InitializeCriticalSection(&m_CSForClients); // Create Accept worker m_AcceptTPWORK = CreateThreadpoolWork(Server::WorkerPostAccept, this, NULL); if (m_AcceptTPWORK == NULL) { ERROR_CODE(GetLastError(), "Could not create AcceptEx worker TPIO."); Destroy(); return false; } m_ShuttingDown = false; SubmitThreadpoolWork(m_AcceptTPWORK); return true; }
int TestPoolWork(int argc, char* argv[]) { int index; PTP_POOL pool; PTP_WORK work; PTP_CLEANUP_GROUP cleanupGroup; TP_CALLBACK_ENVIRON environment; printf("Global Thread Pool\n"); work = CreateThreadpoolWork((PTP_WORK_CALLBACK) test_WorkCallback, "world", NULL); if (!work) { printf("CreateThreadpoolWork failure\n"); return -1; } /** * You can post a work object one or more times (up to MAXULONG) without waiting for prior callbacks to complete. * The callbacks will execute in parallel. To improve efficiency, the thread pool may throttle the threads. */ for (index = 0; index < 10; index++) SubmitThreadpoolWork(work); WaitForThreadpoolWorkCallbacks(work, FALSE); CloseThreadpoolWork(work); printf("Private Thread Pool\n"); if (!(pool = CreateThreadpool(NULL))) { printf("CreateThreadpool failure\n"); return -1; } if (!SetThreadpoolThreadMinimum(pool, 4)) { printf("SetThreadpoolThreadMinimum failure\n"); return -1; } SetThreadpoolThreadMaximum(pool, 8); InitializeThreadpoolEnvironment(&environment); SetThreadpoolCallbackPool(&environment, pool); cleanupGroup = CreateThreadpoolCleanupGroup(); if (!cleanupGroup) { printf("CreateThreadpoolCleanupGroup failure\n"); return -1; } SetThreadpoolCallbackCleanupGroup(&environment, cleanupGroup, NULL); work = CreateThreadpoolWork((PTP_WORK_CALLBACK) test_WorkCallback, "world", &environment); if (!work) { printf("CreateThreadpoolWork failure\n"); return -1; } for (index = 0; index < 10; index++) SubmitThreadpoolWork(work); WaitForThreadpoolWorkCallbacks(work, FALSE); CloseThreadpoolCleanupGroupMembers(cleanupGroup, TRUE, NULL); CloseThreadpoolCleanupGroup(cleanupGroup); DestroyThreadpoolEnvironment(&environment); /** * See Remarks at https://msdn.microsoft.com/en-us/library/windows/desktop/ms682043(v=vs.85).aspx * If there is a cleanup group associated with the work object, * it is not necessary to call CloseThreadpoolWork ! * calling the CloseThreadpoolCleanupGroupMembers function releases the work, wait, * and timer objects associated with the cleanup group. */ /* CloseThreadpoolWork(work); // this would segfault, see comment above. */ CloseThreadpool(pool); return 0; }
int TestPoolWork(int argc, char* argv[]) { int index; PTP_POOL pool; PTP_WORK work; PTP_CLEANUP_GROUP cleanupGroup; TP_CALLBACK_ENVIRON environment; printf("Global Thread Pool\n"); work = CreateThreadpoolWork((PTP_WORK_CALLBACK) test_WorkCallback, "world", NULL); if (!work) { printf("CreateThreadpoolWork failure\n"); return -1; } /** * You can post a work object one or more times (up to MAXULONG) without waiting for prior callbacks to complete. * The callbacks will execute in parallel. To improve efficiency, the thread pool may throttle the threads. */ for (index = 0; index < 10; index++) SubmitThreadpoolWork(work); WaitForThreadpoolWorkCallbacks(work, FALSE); CloseThreadpoolWork(work); printf("Private Thread Pool\n"); pool = CreateThreadpool(NULL); SetThreadpoolThreadMinimum(pool, 4); SetThreadpoolThreadMaximum(pool, 8); InitializeThreadpoolEnvironment(&environment); SetThreadpoolCallbackPool(&environment, pool); cleanupGroup = CreateThreadpoolCleanupGroup(); if (!cleanupGroup) { printf("CreateThreadpoolCleanupGroup failure\n"); return -1; } SetThreadpoolCallbackCleanupGroup(&environment, cleanupGroup, NULL); work = CreateThreadpoolWork((PTP_WORK_CALLBACK) test_WorkCallback, "world", &environment); if (!work) { printf("CreateThreadpoolWork failure\n"); return -1; } for (index = 0; index < 10; index++) SubmitThreadpoolWork(work); WaitForThreadpoolWorkCallbacks(work, FALSE); CloseThreadpoolCleanupGroupMembers(cleanupGroup, TRUE, NULL); CloseThreadpoolCleanupGroup(cleanupGroup); DestroyThreadpoolEnvironment(&environment); CloseThreadpoolWork(work); CloseThreadpool(pool); return 0; }
// // This function is invoked only with Airplane mode change, but not with NFC radio state change. // STDMETHODIMP CNfcRadioManager::OnSystemRadioStateChange( _In_opt_ SYSTEM_RADIO_STATE sysRadioState, _In_ UINT32 uTimeoutSec) { UNREFERENCED_PARAMETER(sysRadioState); UNREFERENCED_PARAMETER(uTimeoutSec); TRACE_METHOD_ENTRY(LEVEL_VERBOSE); HRESULT hr = S_OK; PTP_POOL threadPool = NULL; TP_CALLBACK_ENVIRON callbackEnviron; PTP_CLEANUP_GROUP ptpCleanupGroup = NULL; // Create threadpool to handle all of the radios threadPool = CreateThreadpool(NULL); if (NULL == threadPool) { hr = HRESULT_FROM_WIN32(GetLastError()); } if (SUCCEEDED(hr)) { SetThreadpoolThreadMaximum(threadPool, 50); InitializeThreadpoolEnvironment(&callbackEnviron); SetThreadpoolCallbackPool(&callbackEnviron, threadPool); ptpCleanupGroup = CreateThreadpoolCleanupGroup(); if (NULL == ptpCleanupGroup) { hr = HRESULT_FROM_WIN32(GetLastError()); } else { // Associate the cleanup group with our thread pool SetThreadpoolCallbackCleanupGroup(&callbackEnviron, ptpCleanupGroup, NULL ); } } // Lock so that any adds or removes will not cause list changes during system airplane mode EnterCriticalSection(&m_csAddRemoveLock); if (SUCCEEDED(hr)) { UINT32 i, count = 0; SYSTEM_STATE_SWITCH_CONTEXT* pContext = NULL; hr = m_nfcRadioCollection->GetCount(&count); if (count > 0) { if (SUCCEEDED(hr)) { pContext = (SYSTEM_STATE_SWITCH_CONTEXT*)malloc(count * sizeof(SYSTEM_STATE_SWITCH_CONTEXT)); if (NULL == pContext) { hr = E_OUTOFMEMORY; } } for (i = 0; (SUCCEEDED(hr) && (i < count)); i++) { PTP_WORK ptpThreadWork = NULL; pContext[i].sysRadioState = sysRadioState; m_nfcRadioCollection->GetAt(i, (IRadioInstance**)&(pContext[i].pRadioInstance)); ptpThreadWork = CreateThreadpoolWork( (PTP_WORK_CALLBACK)&CNfcRadioManager::AsyncRadioChange, &(pContext[i]), &(callbackEnviron) ); if (ptpThreadWork == NULL) { // pRadioInstance context was not successfully added to threadpool. hr = pContext[i].pRadioInstance->SetSystemState(sysRadioState); pContext[i].pRadioInstance->Release(); } else { ::SubmitThreadpoolWork(ptpThreadWork); } } } // Wait for all threadpools to drain and clean up threads CloseThreadpoolCleanupGroupMembers(ptpCleanupGroup, FALSE, NULL); if (NULL != pContext) { free(pContext); } } else { // Failed to set up threadpool for parallel system radio change. Only choice is to do it serially now UINT32 i, count = 0; CNfcRadioInstance* pRadioInstance = NULL; hr = m_nfcRadioCollection->GetCount(&count); for (i = 0; (SUCCEEDED(hr) && (i < count)); i++) { hr = m_nfcRadioCollection->GetAt(i, (IRadioInstance**)&pRadioInstance); if (SUCCEEDED(hr)) { hr = pRadioInstance->SetSystemState(sysRadioState); } pRadioInstance->Release(); } } LeaveCriticalSection(&m_csAddRemoveLock); DestroyThreadpoolEnvironment(&callbackEnviron); if(ptpCleanupGroup) { CloseThreadpoolCleanupGroup(ptpCleanupGroup); ptpCleanupGroup = NULL; } if(threadPool) { CloseThreadpool(threadPool); threadPool = NULL; } TRACE_METHOD_EXIT_HR(LEVEL_COND, hr); return hr; }
int _tmain1(int argc, _TCHAR* argv[]) { if (depth == 0) { Display("%d(%d)************\n", GetCurrentProcessId(), GetCurrentThreadId()); return 1; } int multiply = 1; if (argc > 2) { multiply = _ttoi(argv[2]); if (multiply < 1) { Display("multiply should be greater than 1\n"); return -2; } } TP_CALLBACK_ENVIRON CallBackEnviron; InitializeThreadpoolEnvironment(&CallBackEnviron); PTP_POOL pool = CreateThreadpool(NULL); if (NULL == pool) { _tprintf(_T("CreateThreadpool failed. LastError: %u\n"), GetLastError()); } SetThreadpoolThreadMaximum(pool, 100); BOOL bRet = SetThreadpoolThreadMinimum(pool, 20); if (!bRet) { _tprintf(_T("SetThreadpoolThreadMinimum failed. LastError: %u\n"), GetLastError()); } PTP_CLEANUP_GROUP cleanupgroup = CreateThreadpoolCleanupGroup(); if (NULL == cleanupgroup) { _tprintf(_T("CreateThreadpoolCleanupGroup failed. LastError: %u\n"), GetLastError()); } SetThreadpoolCallbackPool(&CallBackEnviron, pool); SetThreadpoolCallbackCleanupGroup(&CallBackEnviron, cleanupgroup, NULL); struct ProcSetup { PROCESS_INFORMATION pi; HANDLE hEvent; HANDLE hWait; HANDLE hOutputRead; HANDLE hErrorRead; HANDLE hInputWrite; int rc; ProcSetup(PROCESS_INFORMATION _pi, HANDLE _hEvent, HANDLE _hWait, HANDLE _hOutputRead, HANDLE _hErrorRead, HANDLE _hInputWrite) : pi(_pi), hEvent(_hEvent), hWait(_hWait), hOutputRead(_hOutputRead), hErrorRead(_hErrorRead), hInputWrite(_hInputWrite) {} }; ProcSetup* pss = (ProcSetup*)calloc(multiply, sizeof(ProcSetup)); for (int i = 0; i < multiply; i++) { Display("%d(%d) Multiply %d out of %d\n", GetCurrentProcessId(), GetCurrentThreadId(), i, multiply); HANDLE hOutputRead, hOutputWrite; HANDLE hErrorRead, hErrorWrite; HANDLE hInputRead, hInputWrite; SECURITY_ATTRIBUTES sa; // Set up the security attributes struct. sa.nLength= sizeof(SECURITY_ATTRIBUTES); sa.lpSecurityDescriptor = NULL; sa.bInheritHandle = TRUE; STARTUPINFO startup_info; ZeroMemory(&startup_info, sizeof(startup_info)); startup_info.cb = sizeof(startup_info); startup_info.dwFlags = STARTF_USESTDHANDLES; PROCESS_INFORMATION process_info; ZeroMemory(&process_info, sizeof(process_info)); TCHAR cmd[1024]; _stprintf(cmd, _T("%s %d"), argv[0], depth-1); BOOL result = CreateProcess(NULL, // ApplicationName cmd, NULL, // ProcessAttributes NULL, // ThreadAttributes TRUE, // InheritHandles CREATE_SUSPENDED, // | CREATE_BREAKAWAY_FROM_JOB, // CreationFlags NULL, NULL, &startup_info, &process_info); pss[i].hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); pss[i].pi = process_info; PTP_WAIT myWait = CreateThreadpoolWait(callback, new WaiterParams(process_info, pss[i].hEvent, &pss[i].rc), &CallBackEnviron); SetThreadpoolWait(myWait, process_info.hProcess, NULL); ResumeThread(process_info.hThread); } HANDLE* events = (HANDLE*)calloc(multiply, sizeof(HANDLE)); for (int i = 0; i < multiply; i++) { events[i] = pss[i].hEvent; } WaitForMultipleObjects(multiply, events, true, INFINITE); int exit_code; for (int i = 0; i < multiply; i++) { PROCESS_INFORMATION* process_info = &pss[i].pi; int texit_code; BOOL ok = GetExitCodeThread(process_info->hThread, reinterpret_cast<DWORD*>(&texit_code)); if (!ok) { printf("*** GetExitCodeThread failed %d\n", GetLastError()); } ok = GetExitCodeProcess(process_info->hProcess, reinterpret_cast<DWORD*>(&exit_code)); if (!ok) { printf("*** GetExitCodeProcess failed %d\n", GetLastError()); } if (texit_code != exit_code) { printf("*** Thread %d exit code %x didn't match process %d exit code %x\n", process_info->dwThreadId, texit_code, process_info->dwProcessId, exit_code); } CloseHandle(process_info->hProcess); CloseHandle(process_info->hThread); // *wp->pRC = exit_code; // exit_code = pss[i].rc; if (exit_code != 1) { printf("Failed to get correct exit code. Got %d instead\n", exit_code); } } for (int i = 0; i < multiply; i++) { CloseHandle(pss[i].hEvent); } free(events); CloseThreadpoolCleanupGroupMembers(cleanupgroup, FALSE, NULL); CloseThreadpoolCleanupGroup(cleanupgroup); CloseThreadpool(pool); DestroyThreadpoolEnvironment(&CallBackEnviron); return exit_code; }