KoreanFoodie's Study

[C++ 게임 서버] 1-2. 쓰레드 생성 본문

Game Dev/Game Server

[C++ 게임 서버] 1-2. 쓰레드 생성

GoldGiver 2023. 7. 7. 21:22

Rookiss 님의 '[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버' 를 들으며 배운 내용을 정리하고 있습니다. 관심이 있으신 분은 꼭 한 번 들어보시기를 추천합니다!

쓰레드 생성

핵심 :

1. 쓰레드를 생성하는 방법은 간단하다. 그냥 std::thread 에 알맞은 함수를 넣어주기만 하면 된다.

2. 쓰레드를 닫아줄 때는 join 으로 닫아주면 된다! 닫기 전, joinable 로 join 가능한지를 체크한다.

3. 쓰레드 객체 생성 시, 함수의 인자에 맞게 갯수를 넣어주어야 잘 동작할 것이다. 쓰레드 객체 생성자 내부는 가변 길이 템플릿으로 구현되어 있다.

이제 쓰레드를 생성하는 기초적인 실습부터 진행해 보자 😂

#include "pch.h"
#include <iostream>
#include "CorePch.h"
#include <atomic>
#include <mutex>
#include <windows.h>
#include <future>

using namespace std;

void HelloThread()
{
	cout << "Hello Thread" << endl;
}

int main()
{
	std::thread t;

	auto id1 = t.get_id(); // 쓰레드의 id
	cout << "id1 : " << id1 << endl;

	t = std::thread(HelloThread);

	int32 count = t.hardware_concurrency(); // CPU 코어 개수
	cout << "CPU core : " << count << endl;

	auto id2 = t.get_id();
	cout << "id2 : " << id2 << endl;

	// 일반적으로, 쓰레드를 join 할 수 있는지 여부를 먼저 체크한 후 join 을 해 준다.
	if (t.joinable())
	{
		t.join();
	}
	 //t.join();

	cout << "Hello Main" << endl;

}

위 코드의 주석을 보면, 쓰레드를 생성해서 id 를 조회하고 있다.

추가적으로 코어 갯수도 체크하고 있는데, 결과값은 다음과 같다 :

보면 쓰레드를 선언만 했을 때는 id 가 0 이지만, 실제 업무(?) 를 맡기게 되면, id 가 변하는 것을 알 수 있다!

쓰레드를 사용했으면, 반드시 join 을 해 주어야 한다! 😊

 

이제 쓰레드들을 이용해서, 각 쓰레드들이 각각 정해진 숫자를 출력하는 코드를 짜 본다고 해 보자.

#include "pch.h"
#include <iostream>
#include "CorePch.h"
#include "pch.h"
#include "Windows.h"
#include <vector>
#include <thread>

using namespace std;

void HelloThread2(int32 input)
{
	cout << input << endl;
}

int main()
{
	std::vector<std::thread> threadVec;

	for (int32 i = 0; i < 10; ++i)
	{
		threadVec.push_back(std::thread(HelloThread2, i));
	}

	
	for (int32 i = 0; i < 10; ++i)
	{
		if (threadVec[i].joinable())
			threadVec[i].join();
	}

	cout << "Main Finished!" << endl;
}

위의 코드를 돌리면, 결과가 다음과 같이 나온다 :

위처럼, 돌릴 때마다 순서는 뒤죽박죽으로 나올 것이다. 😅

 

위 코드에서, 벡터에 새로운 쓰레드 객체를 넣을 때 인자를 넣어주고 있는데, 이는 쓰레드 내부가 다음과 같이 구현되었기 때문에 가능한 것이다! 😮

template <class _Fn, class... _Args, enable_if_t<!is_same_v<_Remove_cvref_t<_Fn>, thread>, int> = 0>
_NODISCARD_CTOR explicit thread(_Fn&& _Fx, _Args&&... _Ax) {
    _Start(_STD forward<_Fn>(_Fx), _STD forward<_Args>(_Ax)...);
}

위 코드는 생성자 부분의 선언인데, 잘 보면 _Args&&... _Ax 라고 되어 있는 부분이, 인자를 받는 부분이라는 것을 알 수 있다.

이 부분이 가변 길이 템플릿으로 구현되어 있으므로, 우리가 넣으려는 함수의 인자 갯수에 맞게 추가로 인자를 넣어주기만 하면, 쓰레드 객체를 간편하게 생성할 수 있는 것이다 😊

Comments