【转载】C++线程入口函数的几种方式

原文链接:http://my.oschina.net/osbin/blog/215125

一、全局函数作为线程的入口函数 二、静态成员函数作为线程的入口函数 三、友元函数作为线程的入口函数 四、无参成员函数作为线程的入口函数
假设线程入口函数和创建线程函数原型如下:

线程入口函数原型:
typedef void* (*FNTHREAD)(void *pParam);
其中:pParam传递给线程的参数。

创建线程函数原型:
THREAD ThreadCreate(void *pParam, FNTHREAD fnThreadProc) ;
其中:pParam传递给线程的参数。fnThreadProc线程入口函数。THREAD函数返回类型,线程句柄。

不考虑等待线程结束、释放线程句柄...等问题。


一、全局函数作为线程的入口函数

 

01 void* FunThreadGlobal(void *pParam) ;
02  
03 class CThreadGlobal
04 {
05 public:
06     THREAD ThreadRun()
07     {
08         return ThreadCreate(this, FunThreadGlobal) ;
09     }
10      
11     void* ThreadProc()
12     {
13         cout<<"CThreadGlobal"<<endl ;
14         return NULL ;
15     }
16 };
17  
18 void* FunThreadGlobal(void *pParam)
19 {
20     CThreadGlobal *p = static_cast<CThreadGlobal *>(pParam) ;
21     return (p != NULL) ? p->ThreadProc() : NULL ;
22 }



二、静态成员函数作为线程的入口函数

 

01 class CThreadStatic
02 {
03 public:
04     THREAD ThreadRun()
05     {
06         return ThreadCreate(this, FunThreadStatic) ;
07     }
08      
09     void* ThreadProc()
10     {
11         cout<<"CThreadStatic"<<endl ;
12         return NULL ;
13     }
14 private:
15     static void* FunThreadStatic(void *pParam) ;
16 };
17  
18 void* CThreadStatic::FunThreadStatic(void *pParam)
19 {
20     CThreadStatic *p = static_cast<CThreadStatic *>(pParam) ;
21     return (p != NULL) ? p->ThreadProc() : NULL ;
22 }



三、友元函数作为线程的入口函数

 

01 class CThreadFriend
02 {
03 public:
04     friend void* FunThreadFriend(void *pParam) ;
05      
06     THREAD ThreadRun()
07     {
08         return ThreadCreate(this, FunThreadFriend) ;
09     }
10      
11     void* ThreadProc()
12     {
13         cout<<"CThreadFriend"<<endl ;
14         return NULL ;
15     }
16 };
17  
18 static void* FunThreadFriend(void *pParam)
19 {
20     CThreadFriend *p = static_cast<CThreadFriend *>(pParam) ;
21     return (p != NULL) ? p->ThreadProc() : NULL ;
22 }



四、无参成员函数作为线程的入口函数
类成员函数有个隐含的this指针,对于类成员函数ReturnType Class::MemFun(ParameterList...) ;
可以看成是ReturnType MemFun(Class * this, ParameterList...) ;
因此无参的成员函数刚好可以当线程的入口函数。但C++不支持将成员函数指针强制转换成其它类型的指针,
成员函数ReturnType Class::MemFun();直接强制类型转换 FNTHREAD fun = (FNTHREAD)&Class::MemFun; 这样写法将引起编译错误。
这种方式不行,那么就换别的。条条大道通罗马,能达到目的就行。下面介绍两种实现方式:

4.1、函数模板方式

01 template<typename T, typename F>
02 THREAD ThreadCreateTemplate(T *t, F f)
03 {
04     typedef void* (T::*THISCALLFUN)(); //指向类T的无参成员函数的指针类型
05     THISCALLFUN fnTcf = (THISCALLFUN)f; //这样fnTcf就保存了成员函数的地址
06     FNTHREAD fnFun = *(FNTHREAD*)&fnTcf ; //将fnTcf取地址以后,再取该地址的内容(成员函数的地址)
07     return ThreadCreate(t, fnFun) ; //t就当this指针,
08 }
09  
10 class CThreadTemplate
11 {
12 public:
13     THREAD ThreadRun()
14     {
15         return ThreadCreateTemplate(this, &CThreadTemplate::ThreadProc) ;
16     }
17      
18     void* ThreadProc()
19     {
20         cout<<"CThreadTemplate"<<endl ;
21         return NULL ;
22     }
23 };



4.2、变参函数方式
虽然不能将成员函数指针强制转换成其它类型的指针,但尝试发现可以把成员函数指针传给可变参数的函数。

01 THREAD ThreadCreateVarParam(void *pParam, ...)
02 {
03     FNTHREAD fnFun = NULL;
04     va_list pArgList ;
05     va_start (pArgList, pParam) ;
06     fnFun = *(FNTHREAD *)pArgList ;
07     va_end (pArgList) ;
08     return fnFun != NULL ? ThreadCreate(pParam, fnFun) : (THREAD)0 ;
09 }
10  
11 class CThreadVarParam
12 {
13 public:
14     THREAD ThreadRun()
15     {
16         return ThreadCreateVarParam(this, &CThreadVarParam::ThreadProc) ;
17     }
18      
19     void* ThreadProc()
20     {
21         cout<<"CThreadVarParam"<<endl ;
22         return NULL ;
23     }
24 };

 

 

 

导航