在pthread的線程函數中,使用類的非靜態成員函數來執行

大家知道,pthread_create()函數的線程函數必須是靜態的函數以標準的__cdecl的方式調用的,而C++的成員函數是以__thiscall的方式調用的,相當於一個普通函數有一個默認的const ClassType* this參數

為數據封裝的需要,我常常把線程函數封裝在一個類的內部,定義一個類的私有靜態成員函數來作為pthread的線程函數,通常如下:

class MyClass
{
public:
    MyClass();
private:
    pthread_t tid;
    static void* _thread_t(void* param);
};

void* MyClass::_thread_t(void* param)
{
    MyClass* pThis = (MyClass*)param;
    pThis->DoSomeThing();
    //...
    return NULL;
}

MyClass::MyClass()
{
    pthread_create(&tid, NULL, _thread_t, this);
}

可以看見,創建線程的時候,把this指針作為線程的參數傳入,然後在線程函數中用一個變量pThis來代替this指針。這樣的做法比較醜陋,而且每次都要手動強制轉換,很麻煩。

後來看了一些模版的資料,找到了一個簡便些的技巧:

template <typename TYPE, void (TYPE::*_RunThread)() >
void* _thread_t(void* param)
{
    TYPE* This = (TYPE*)param;
    // 多 wrapper 一層讓_RunThread 不需要是static 函數
    This->_RunThread();
    return NULL;
}

class MyClass
{
public:
    MyClass();
    void _RunThread();
private:
    pthread_t tid;

};

void MyClass::_RunThread()
{
    this->DoSomeThing();
    //...
}

MyClass::MyClass()
{
    pthread_create(&tid, NULL, _thread_t<MyClass, &MyClass::_RunThread>, this);
}

函數模版不單可以替換類型本身,還能替換類型的成員函數。

注意:

1、名稱只能是_RunThread,不能在指定模版參數的時候修改;
2、_RunThread只能是public的,除非把_thread_t定義到MyClass的內部。