#include "StdAfx.h"
|
#include "IOCPHandler.h"
|
#include <assert.h>
|
|
typedef unsigned (__stdcall *PTHREAD_START) (void *);
|
|
#define BEGINTHREADEX(psa, cbStack, pfnStartAddr, \
|
pvParam, fdwCreate, pdwThreadId) \
|
((HANDLE)_beginthreadex( \
|
(void *) (psa), \
|
(unsigned) (cbStack), \
|
(PTHREAD_START) (pfnStartAddr), \
|
(void *) (pvParam), \
|
(unsigned) (fdwCreate), \
|
(unsigned *) (pdwThreadId)))
|
|
CIOCPHandler::CIOCPHandler(void)
|
{
|
m_hIOCP=NULL;
|
m_nLiveThreadNum = 0;
|
m_nCreatedThreadNumber = 0;
|
m_EventExitWorkerThread = NULL;
|
}
|
|
CIOCPHandler::~CIOCPHandler(void)
|
{
|
if(m_hIOCP)
|
{
|
CloseHandle(m_hIOCP);
|
m_hIOCP = NULL;
|
}
|
if(m_EventExitWorkerThread)
|
{
|
CloseHandle(m_EventExitWorkerThread);
|
m_EventExitWorkerThread = NULL;
|
}
|
}
|
|
/*!
|
* \brief
|
* IOCP »ý¼º ¹× ÃʱâÈ
|
*
|
* \param nMaxNumberOfConcurrentThreads
|
* Concurrent Thread ÀÇ °¹¼ö
|
*
|
* \param pnOutErrCode
|
* ¿¡·¯ »óȲ ½Ã¿¡ ¿ÜºÎ·Î ´øÁ®Áú ¿¡·¯ÄÚµå, NULL ÀÌ µé¾î¿À¸é ¿¡·¯Äڵ带 ´øÁöÁö ¾Ê´Â´Ù.
|
*
|
* \returns
|
* ¼º°ø = TRUE, ½ÇÆÐ = FALSE
|
*/
|
BOOL CIOCPHandler::Create(int nMaxNumberOfConcurrentThreads, int* pnOutErrCode)
|
{
|
m_hIOCP = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, nMaxNumberOfConcurrentThreads);
|
if(m_hIOCP == NULL && pnOutErrCode != NULL)
|
{
|
*pnOutErrCode = GetLastError();
|
}
|
|
return (m_hIOCP!=NULL);
|
}
|
|
/*!
|
* \brief
|
* Thread Pool À» »ý¼º!
|
*
|
* \param piProcessThread
|
* IIocpProcessThread ÀÎÅÍÆäÀ̽º¸¦ »ó¼Ó¹ÞÀº Ŭ·¡½º¿¡ ´ëÇÑ Æ÷ÀÎÅÍ.\n
|
* Áï ¾²·¹µå Ç®¿¡ µé¾î°¥ ¾²·¹µå ÇÔ¼ö°¡ ±¸ÇöµÈ Ŭ·¡½ºÀÇ Æ÷ÀÎÅÍ
|
*
|
* \param nNumOfPooledThread
|
* Ç®¸µÇÒ ¾²·¹µå °³¼ö, 0ÀÌ¸é µðÆúÆ® °ª¿¡ ¸ÂÃß¾îÁü
|
*
|
* \returns
|
* TRUE
|
*
|
|
*
|
* IOCP Worker Thread Ç®À» ¸¸µë
|
*
|
*/
|
BOOL CIOCPHandler::CreateThreadPool(IIOCPProcessThread* piProcessThread, int nNumOfPooledThread)
|
{
|
assert(piProcessThread);
|
assert(nNumOfPooledThread >= 0);
|
if(nNumOfPooledThread == 0)
|
{
|
SYSTEM_INFO si;
|
GetSystemInfo(&si);
|
|
// µðÆúÆ® ¾²·¹µå ¼ö·Î
|
// 2 * ÇÁ·Î¼¼¼¼ö + 1 ÀÇ °ø½ÄÀ» µû¶úÀ½
|
m_nCreatedThreadNumber = si.dwNumberOfProcessors * 2 + 1;
|
}
|
else
|
{
|
m_nCreatedThreadNumber = nNumOfPooledThread;
|
}
|
|
DWORD dwThreadId;
|
for(int i=0; i < m_nCreatedThreadNumber; i++)
|
{
|
dwThreadId = 0;
|
HANDLE hWorker = CreateThread(NULL, 0, IocpWorkerThreadStartingPoint, piProcessThread, 0, &dwThreadId);
|
CloseHandle(hWorker);
|
hWorker = NULL;
|
// ÇöÀç »ì¾ÆÀÖ´Â ¾²·¹µåÀÇ °³¼ö¸¦ ÆÄ¾ÇÇϱâ À§ÇØ µ¿±âÈ °´Ã¼¸¦ µÒ
|
InterlockedIncrement(&m_nLiveThreadNum);
|
}
|
// ¿öÄ¿¾²·¹µåÀÇ Á¾·á È®ÀÎ À̺¥Æ® ÃʱâÈ
|
m_EventExitWorkerThread = CreateEvent(NULL, TRUE, FALSE, NULL);
|
|
return TRUE;
|
}
|
|
/*!
|
* \brief
|
* IOCP ¿öÄ¿ ¾²·¹µå ½ÃÀÛ Æ÷ÀÎÆ®·Î¼¸¸ÀÇ ¿ªÈ°
|
*
|
* \param pvParam
|
* IIOCPProcessThread*
|
*
|
* \returns
|
* 0 : ¼º°ø
|
*
|
*/
|
DWORD __stdcall CIOCPHandler::IocpWorkerThreadStartingPoint(PVOID pvParam)
|
{
|
IIOCPProcessThread* piProcessThread=(IIOCPProcessThread*)pvParam;
|
piProcessThread->ProcessingThread();
|
|
return 0;
|
}
|
|
/*!
|
* \brief
|
* ÇöÀç µ¹°í ÀÖ´Â ¾²·¹µå ¸ðµÎ Á×ÀÓ
|
*
|
*
|
* ÇöÀç »ý¼ºµÈ IOCP Ç®À» Ž»öÇÏ¿© IOCP ¿öÄ¿¾²·¹µå¿¡ Á¾·á ¸Þ¼¼Áö¸¦ Àü´ÞÇÑ´Ù.
|
*
|
*/
|
void CIOCPHandler::CloseAllThreads(void)
|
{
|
//TRACE("!---- Start -- void CIOCPHandler::CloseAllThreads(void)! Thread Num = [%d]\n",m_nCreatedThreadNumber);
|
for(int i=0;i<m_nCreatedThreadNumber;i++)
|
{
|
int nErrorCode = 0;
|
BOOL bRet = PostCompletionStatus(THREAD_DIE,0,NULL,&nErrorCode);
|
if(bRet == FALSE)
|
{
|
//TRACE("PostQueuedCompletionStatus retrun 0 Error Code : %d \n",nErrorCode );
|
}
|
else
|
{
|
//TRACE("PostQueuedCompletionStatus retrun Success ThreadId[%d] \n",i );
|
}
|
|
}
|
//TRACE("!---- End -- void CIOCPHandler::CloseAllThreads(void)! Thread Num = [%d]\n",m_nCreatedThreadNumber);
|
}
|
|
/*!
|
* \brief
|
* IO Completion Queue¿¡ ÇÑ ¿Ï·á ÆÐŶ¸¦ »ç¿ëÀÚ Á¤ÀÇ·Î Ãß°¡
|
*
|
* \param CompletionKey
|
* »ç¿ëÀÚ Á¤ÀÇ ¿Ï·á ÆÐŶ¿¡ µé¾î°¥ Completion Key
|
*
|
* \param dwBytesTransferred
|
* »ç¿ëÀÚ Á¤ÀÇ ¿Ï·á ÆÐŶ¿¡ µé¾î°¥ ¹ÙÀÌÆ®¼ö(0 µðÆúÆ®)
|
*
|
* \param pOverlapped
|
* »ç¿ëÀÚ Á¤ÀÇ ¿Ï·á ÆÐŶ¿¡ µé¾î°¡´Â ¿À¹ö·¦µå ±¸Á¶Ã¼(NULL µðÆúÆ®)
|
*
|
* \param pnOutErrCode
|
* ¿¡·¯ »óȲ ½Ã¿¡ ¿ÜºÎ·Î ´øÁ®Áú ¿¡·¯ÄÚµå, NULL ÀÌ µé¾î¿À¸é ¿¡·¯Äڵ带 ´øÁöÁö ¾Ê´Â´Ù.
|
*
|
* \returns
|
* ¼º°ø = TRUE, ½ÇÆÐ = FALSE
|
*
|
*/
|
BOOL CIOCPHandler::PostCompletionStatus(ULONG_PTR CompletionKey, DWORD dwBytesTransferred, OVERLAPPED* pOverlapped, int* pnOutErrCode)
|
{
|
BOOL ret = PostQueuedCompletionStatus(m_hIOCP, dwBytesTransferred, CompletionKey, pOverlapped);
|
if(!ret && pnOutErrCode != NULL)
|
{
|
*pnOutErrCode = GetLastError();
|
}
|
|
return ret;
|
}
|
|
/********************************************************************************/
|
// ¼ÒÄϰú IOCP ¿Í ¿¬°á
|
// hSocket : IOCP ¿Í ¿¬°áµÉ ¼ÒÄÏ
|
// CompletionKey : ¿¬°áµÇ¸é¼ ¾²¿©Áú Completion Key
|
// pnOutErrCode : À§¿Í »óµ¿
|
/********************************************************************************/
|
|
|
/*!
|
* \brief
|
* ¼ÒÄϰú IOCP ¿Í ¿¬°á
|
*
|
* \param hSocket
|
* IOCP ¿Í ¿¬°áµÉ ¼ÒÄÏ
|
*
|
* \param CompletionKey
|
* ¿¬°áµÇ¸é¼ ¾²¿©Áú Completion Key
|
*
|
* \param pnOutErrCode
|
* ¿¡·¯ »óȲ ½Ã¿¡ ¿ÜºÎ·Î ´øÁ®Áú ¿¡·¯ÄÚµå, NULL ÀÌ µé¾î¿À¸é ¿¡·¯Äڵ带 ´øÁöÁö ¾Ê´Â´Ù.
|
*
|
* \returns
|
* ¼º°ø = 1, ½ÇÆÐ = 0
|
|
*/
|
BOOL CIOCPHandler::Associate(SOCKET hSocket, ULONG_PTR CompletionKey, int* pnOutErrCode)
|
{
|
assert(hSocket != INVALID_SOCKET);
|
|
return Associate((HANDLE)hSocket, CompletionKey, pnOutErrCode);
|
}
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
//
|
// ÆÄÀÏ ÇÚµé°ú IOCP ¿ÍÀÇ ¿¬°á
|
// hDevice : IOCP ¿Í ¿¬°áµÉ µð¹ÙÀ̽º
|
// CompletionKey : ¿¬°áµÇ¸é¼ ¾²¿©Áú Completion Key
|
// pnOutErrCode : À§¿Í »óµ¿
|
//
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
/*!
|
* \brief
|
* ÆÄÀÏ ÇÚµé°ú IOCP ¿ÍÀÇ ¿¬°á
|
*
|
* \param hDevice
|
* IOCP ¿Í ¿¬°áµÉ µð¹ÙÀ̽º
|
*
|
* \param CompletionKey
|
*¿¬°áµÇ¸é¼ ¾²¿©Áú Completion Key
|
*
|
* \param pnOutErrCode
|
* ¿¡·¯ »óȲ ½Ã¿¡ ¿ÜºÎ·Î ´øÁ®Áú ¿¡·¯ÄÚµå, NULL ÀÌ µé¾î¿À¸é ¿¡·¯Äڵ带 ´øÁöÁö ¾Ê´Â´Ù.
|
*
|
* \returns
|
* ¼º°ø = 1, ½ÇÆÐ = 0
|
*/
|
BOOL CIOCPHandler::Associate(HANDLE hDevice, ULONG_PTR CompletionKey, int* pnOutErrCode)
|
{
|
assert(hDevice != INVALID_HANDLE_VALUE);
|
assert(CompletionKey != 0);
|
|
HANDLE retHandle = CreateIoCompletionPort(hDevice, m_hIOCP, CompletionKey, 0);
|
if(retHandle != m_hIOCP && pnOutErrCode != NULL)
|
{
|
*pnOutErrCode = GetLastError();
|
}
|
|
return (retHandle == m_hIOCP);
|
}
|
|
|
|
/*!
|
* \brief
|
* IO Completion Queue¿¡¼ ¿Ï·á ÆÐŶÀ» ¾ò¾î¿Â´Ù.
|
*
|
* \param pOutCompletionKey
|
* IO Completon Å¥¿¡¼ »©³»¿Â ·¹ÄÚµåÀÇ Completion Key
|
*
|
* \param pdwOutBytesTransferred
|
* IO Completon Å¥¿¡¼ »©³»¿Â ·¹ÄÚµåÀÇ ¹ÙÀÌÆ®¼ö(0 µðÆúÆ®)
|
*
|
* \param pOutOverlapped
|
* IO Completon Å¥¿¡¼ »©³»¿Â ·¹ÄÚµåÀÇ ¿À¹ö·¦µå ±¸Á¶Ã¼(NULL µðÆúÆ®)
|
*
|
* \param pnOutErrCode
|
* ¿¡·¯ »óȲ ½Ã¿¡ ¿ÜºÎ·Î ´øÁ®Áú ¿¡·¯ÄÚµå, NULL ÀÌ µé¾î¿À¸é ¿¡·¯Äڵ带 ´øÁöÁö ¾Ê´Â´Ù.
|
*
|
* \param dwWaitingTime
|
* ¿Ï·á ÆÐŶÀÌ ¾øÀ» ½Ã¿¡ ±â´Ù¸± ½Ã°£ (µðÆúÆ®: ¹«ÇÑ´ë)
|
*
|
* \returns
|
* ¼º°ø = 1, ½ÇÆÐ = 0
|
*
|
*/
|
BOOL CIOCPHandler::GetCompletionStatus(ULONG_PTR* pOutCompletionKey, LPDWORD pdwOutBytesTransferred
|
, LPOVERLAPPED* pOutOverlapped, int* pnOutErrCode, DWORD dwWaitingTime)
|
{
|
BOOL ret = GetQueuedCompletionStatus(m_hIOCP, pdwOutBytesTransferred, pOutCompletionKey
|
, pOutOverlapped, dwWaitingTime);
|
if(!ret && pnOutErrCode != NULL)
|
{
|
*pnOutErrCode=GetLastError();
|
}
|
|
return ret;
|
}
|