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–