2007-11-12
pthread in C++
Linux下的编程一直是C语言的天下,但老是用C感觉写的很乏味。用面向对象方法编程,听着都倍有面子。于是决定先在的这个项目用C++来写。虽然不一定能“以C++的思想”来写C++,少会有C++的样子。
但是问题来了:我需要在程序中动态创建一个线程,而pthread不接受C++类的成员函数作为参数。
原因也很简单,类成员是在类被实例化成为对象后才存在的,即在编译时是不存在的,编译器无法取得函数的确切入口地址,自然无法通过编译。
照这个分析,如果把要调用的类成员函数声明为静态的,pthread_create就可以找到函数的地址了。但这样一来的话,由于类中的静态函数无法调用类的非静态成员。线程函数的功能就受到了很大限制,也就没有比要将其放在类中了。
最容易想到的解决方案就是写个C函数,然后再C函数中调用C++对象的成员函数。
比如类为
class foo(){ public : thread(); } class *f; void *bar(void *arg){ f->thread(); return NULL; } int main(){ ......... f=new foo(); pthread_create(&tid,&tattr,bar,NULL); }
显然这种发法太笨了,而且对象只能是全局的。
注意到线程函数bar可以有一个任意类型的指针作为参数,那我们何不将对象通过这个指针将对象变为bar的一个参数,从而让我们的程序好看一些。
class foo(){ public : thread(); } void *bar(void *args){ foo *f=(foo *)args; f.thread(); return NULL; } int main(){ ......... foo *f=new foo(); pthread_create(&tid,&tattr,bar,f); }
如果把上述两种方法结合起来即对象中的静态函数+通过指针参数传递对象,那又会怎么样呢?
class foo(){ public : int thread(); static void *wrapper(void *args){ foo *f=static_cast<foo *>(args); f->thread(); return NULL; } } int main(){ ......... foo *f=new foo(); pthread_create(&tid,&tattr,foo::wrapper,&f); }
现在,强迫症患者,是不是觉得整洁清楚很多了呢?
–Reference–
http://www.osix.net/modules/article/?id=450
–EOF–