IOCP에서 사용하는 WorkerThread를 구현했다.

기본적으로 GQCS( GetQueuedCompletionStatus )가 return 되기를 대기하고, return된 값에 따라 처리한다.

 

return 된 값이 0일 경우 fin 을 받은 것이므로 종료 처리하고, 0보다 클 경우 적절하게 recv 또는 send 처리한다.

 

unsigned __stdcall CoreNetwork::WorkerThreadProc(void* argument)
{
	CoreNetwork* instance = (CoreNetwork*)argument;

	if (instance != nullptr)
	{
		Session* completeSession = nullptr;
		while (1)
		{
			DWORD transferred = 0;
			OVERLAPPED* myOverlapped = nullptr;
			int completeRet;
			DWORD GQCSError;

			do
			{
				completeRet = GetQueuedCompletionStatus(instance->_HCP, &transferred,
					(PULONG_PTR)&completeSession, (LPOVERLAPPED*)&myOverlapped, INFINITE);
				if (myOverlapped == nullptr)
				{
					GQCSError = WSAGetLastError();
					wcout << L"MyOverlapped NULL " << GQCSError << endl;
					return -1;
				}

				// transferred가 0이라면 fin 패킷을 받은것이므로 종료처리한다.
				if (transferred == 0)
				{
					break;
				}

				// 전달받은 overlapped가 recvOverlapped라면 recv 완료 처리를 진행한다.
				if (myOverlapped == &completeSession->recvOverlapped)
				{
					instance->RecvComplete(completeSession, transferred);
				}
				// 전달받은 overlapped가 sendOverlapped라면 send 완료 처리를 진행한다.
				else if (myOverlapped == &completeSession->sendOverlapped)
				{
					instance->SendComplete(completeSession);
				}
			} while (0);

			// IO 처리가 하나 끝났으므로 IOCount를 감소시킨다.
			if (InterlockedDecrement64(&completeSession->IOBlock->IOCount) == 0)
			{
				instance->ReleaseSession(completeSession);
			}
		}
	}

	return 0;
}

기본적으로 Node.js는 단일 스레드에서 실행되고, 이벤트 루프는 한번에 하나의 프로세스만 발생한다.

따라서 CPU 집약적인 작업 ( 대규모 데이터 처리, 이미지 변환 등 )이 메인 스레드를 차단 할 수 있다.

 

Worker Thread

CPU 집약적인 작업을 실행할 때 메인 스레드의 성능과 응답성을 유지하기 위해 사용하는 백그라운드 스레드다.

Wokrer는 비동기적으로 실행되고, JavaScript의 싱글 스레드 모델을 보완하여 멀티스레드 환경을 제공한다.

 

1. 독립된 스레드

 Woker는 메인 스레드와 별도의 실행 컨텍스트에서 동작하며, 독립적인 global scope를 가진다.

 

2. 메세지 기반 통신

 메인 스레드와 Worker는 postMessage()와 onMessage를 통해 데이터를 교환한다.

 

woker.js

// Worker 내부 코드
onmessage = function(event) {
  const data = event.data; // 메인 스레드에서 받은 데이터
  const result = data * 2; // 작업 처리
  postMessage(result); // 결과 반환
};

 

main.js

// 메인 스레드 코드
const worker = new Worker('worker.js');

// 메시지 보내기
worker.postMessage(10);

// 메시지 받기
worker.onmessage = function(event) {
  console.log('Worker로부터 받은 결과:', event.data); // 20
};

// Worker 종료
worker.terminate();

 

+ Recent posts