🔧 1. 설계 목표
- 직접 thread를 생성하지 않고,
ThreadManager를 통해 통합 관리.
- 각 쓰레드에게 고유한 Thread ID를 부여 (
TLS 활용).
- 쓰레드 시작 시 초기화, 종료 시 정리 작업을 자동 수행.
- 서버 전반에서 유용하게 사용할 수 있도록 전역 관리 인스턴스 제공.
🧠 2. 전처리: 핵심 유틸 정의
✅ Crash & Assert 매크로
#define CRASH(cause) \
{ \
uint32* crash = nullptr; \
__analysis_assume(crash != nullptr); \
*crash = 0xDEADBEEF; \
}
#define ASSERT_CRASH(expr) \
{ \
if (!(expr)) \
{ \
CRASH("ASSERT_CRASH"); \
__analysis_assume(expr); \
} \
}
- CRASH: 강제로 크래시를 발생시키는 매크로.
- ASSERT_CRASH: 조건이 false일 때 강제로 크래시 발생.
__analysis_assume(expr)는 컴파일러의 불필요한 경고 방지용.
🧵 3. ThreadManager 클래스 구조
📁 ThreadManager.h
class ThreadManager
{
public:
ThreadManager();
~ThreadManager();
void Launch(function<void(void)> callback);
void Join();
static void InitTLS();
static void DestroyTLS();
private:
Mutex _lock;
vector<thread> _threads;
};
Launch(): 새로운 쓰레드 생성 및 등록
Join(): 모든 쓰레드가 종료될 때까지 대기
InitTLS(): TLS 초기화 및 ID 부여
DestroyTLS(): TLS 정리
🔄 4. ThreadManager 구현
📁 ThreadManager.cpp
ThreadManager::ThreadManager()
{
InitTLS();
}
ThreadManager::~ThreadManager()
{
Join();
}
void ThreadManager::Launch(function<void(void)> callback)
{
LockGuard guard(_lock);
_threads.push_back(thread([=]()
{
InitTLS();
callback();
DestroyTLS();
}));
}
void ThreadManager::Join()
{
for (thread& t : _threads)
{
if (t.joinable())
t.join();
}
_threads.clear();
}
void ThreadManager::InitTLS()
{
static Atomic<uint32> SThreadId = 1;
LThreadId = SThreadId.fetch_add(1);
}
void ThreadManager::DestroyTLS()
{
}
📌 핵심 설명
- Launch
- 쓰레드를 생성할 때
InitTLS()로 ID 부여 → callback() 실행 → DestroyTLS()로 정리.
- Join
- 모든 쓰레드가
joinable 상태가 될 때까지 대기.
🧵 5. Thread Local Storage (TLS)
📁 CoreTls.h & CoreTls.cpp
extern thread_local uint32 LThreadId;
thread_local uint32 LThreadId = 0;
thread_local: 각 쓰레드마다 독립적인 변수 생성.
InitTLS()에서 ID를 할당받고 이후 각 쓰레드는 LThreadId를 통해 자신을 식별 가능.
🌐 6. ThreadManager 전역 관리
📁 CoreGlobal.h & CoreGlobal.cpp
extern class ThreadManager* GThreadManager;
class CoreGlobal
{
public:
CoreGlobal() { GThreadManager = new ThreadManager(); }
~CoreGlobal() { delete GThreadManager; }
} GCoreGlobal;
- 프로그램이 시작되면
GCoreGlobal이 자동 생성되며 ThreadManager를 초기화.
🧪 7. ThreadManager 사용 예시
📁 GameServer.cpp
void ThreadMain()
{
while (true)
{
cout << "Hello! I am thread... ID: " << LThreadId << endl;
this_thread::sleep_for(1s);
}
}
int main()
{
for (int32 i = 0; i < 5; i++)
{
GThreadManager->Launch(ThreadMain);
}
GThreadManager->Join();
}
✅ 실행 결과
Hello! I am thread... ID: 2
Hello! I am thread... ID: 3
Hello! I am thread... ID: 4
Hello! I am thread... ID: 5
Hello! I am thread... ID: 6
- 각 쓰레드는 서로 다른 ID를 갖고 독립적으로 동작.
Launch → InitTLS → callback → DestroyTLS 순서로 동작.