Files
Sun1602/Server/ShopServer/Uitl/WorkerThreadPool.cpp
T
2022-10-26 12:25:11 +08:00

165 lines
3.3 KiB
C++

#include "stdafx.h"
#include "WorkerThreadPool.h"
CWorkerThreadPool::CWorkerThreadPool() :
m_hIOCP(NULL),
m_dwThreadCount(0)
{
}
CWorkerThreadPool::~CWorkerThreadPool()
{
}
bool CWorkerThreadPool::CreateThreadPool(DWORD dwThreadCnt)
{
if(MAX_THREAD_COUNT < dwThreadCnt) //스레드 최대 생성 개수 이상 생성하려고 하면 실패
{
return false;
}
m_hIOCP = ::CreateIoCompletionPort( INVALID_HANDLE_VALUE, 0, 0, dwThreadCnt ); // 메인 IOCP 핸들 생성
if(NULL == m_hIOCP)
{
return false;
}
m_dwThreadCount = dwThreadCnt;
UINT threadID = 0;
for(DWORD i = 0 ; i < m_dwThreadCount ; i++ ) // 작업 스레드를 생성한다.
{
m_hThread[i] = (HANDLE)_beginthreadex(0, 0, WorkThreadProc, (LPVOID)this, 0, &threadID);
}
return true;
}
UINT __stdcall CWorkerThreadPool::WorkThreadProc( LPVOID lParam )
{
BOOL ret;
DWORD transBytes;
DWORD_PTR key;
OVERLAPPED result;
HANDLE hIOCP = ((CWorkerThreadPool*)lParam)->m_hIOCP;
::CoInitialize(NULL);
while(true)
{
ret = ::GetQueuedCompletionStatus( hIOCP, &transBytes, &key, (LPOVERLAPPED*)&result, INFINITE);
if(IOCPTHREAD_CLOSE == key) //종료신호를 받았을때
{
break;
}
else
{
((CWorkerThread*)key)->Run();
}
}
::CoUninitialize();
return 0;
}
UINT __stdcall CWorkerThreadPool::SessionThreadProc( LPVOID parameter )
{
::CoInitialize(NULL);
if(NULL == ((CWorkerThread*)parameter)->GetExitEvent())
{
((CWorkerThread*)parameter)->RunProc();
}
else
{
while(true)
{
if(WaitForSingleObject(((CWorkerThread*)parameter)->GetExitEvent(), 1) == WAIT_OBJECT_0)
{
break;
}
((CWorkerThread*)parameter)->RunProc();
}
}
::CoUninitialize();
return 0;
}
void CWorkerThreadPool::DestoryThreadPool()
{
if(NULL != m_hIOCP)
{
for (DWORD i = 0; i < m_dwThreadCount; i++)
{
PostQueuedCompletionStatus(m_hIOCP, 0, IOCPTHREAD_CLOSE, NULL); //스레드에 종료 메시지를 보낸다.
}
// 작업스레드들이 종료될때 까지 대기한다.
DWORD dwRet = WaitForMultipleObjects( m_dwThreadCount, m_hThread, TRUE, 2000);
// 메인 IOCP 핸들 닫기
CloseHandle(m_hIOCP);
m_hIOCP = NULL;
//스레드 핸들 닫기
for(DWORD i = 0 ; i < m_dwThreadCount ; i++ )
{
CloseHandle(m_hThread[i]);
}
m_dwThreadCount = 0;
}
}
BOOL CWorkerThreadPool::AddJob(CWorkerThread* pWorker)
{
if(NULL == m_hIOCP) return FALSE;
return PostQueuedCompletionStatus(m_hIOCP, 0, (DWORD_PTR)pWorker, NULL);
}
void CWorkerThreadPool::AddJobThread(CWorkerThread* pWorker)
{
//CWorkerThread* pWorker = new CWorkerThread;
UINT threadID = 0;
pWorker->SetExitEvent();
HANDLE hThread = (HANDLE)_beginthreadex(0, 0, SessionThreadProc, (LPVOID)pWorker, 0, &threadID);
pWorker->SetThreadHandle(hThread);
m_vecThread.push_back(pWorker);
}
void CWorkerThreadPool::AllStopJobThread()
{
while(m_vecThread.empty()==false) // worker thread 정리
{
CWorkerThread* pWorker = m_vecThread.back();
m_vecThread.pop_back();
pWorker->Terminate();
pWorker->WaitThread(250);
//delete pWorker;
pWorker = NULL;
}
}
void CWorkerThreadPool::OnTimr(HANDLE hRequest, DWORD dwRequest)
{
// 기본적으로 락처리를 해야 하지만, 정적으로 사용하는 구조라서 락처리를 따로 하지는 않는다.
WorkerIter Iter = m_vecThread.begin();
while(Iter != m_vecThread.end())
{
CWorkerThread* pWorker = (*Iter);
if(pWorker)
pWorker->OnTimer(hRequest, dwRequest);
Iter++;
}
}