🔧 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(); // Main 쓰레드용
}

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; // 쓰레드 고유 ID

// 정의
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를 갖고 독립적으로 동작.
  • LaunchInitTLScallbackDestroyTLS 순서로 동작.

profile
李家네_공부방

0개의 댓글