我想知道将成员函数传递给pthread_clean_push
的方法。我不想将清理函数声明为静态并传递对象的引用。以下是场景
class Foo{
public:
Foo(string name):name(name){};
void setBar1(){bar1=malloc(4);sleep(20);};
void setBar2(){bar2=malloc(10);sleep(50);};
void cleanBar1(void* arg){free(bar1);};
void cleanBar2(void* arg){free(bar2);};
private:
string name;
void* bar1;
void* bar2;
};
void* myPThread(void* arg){
Foo theFoo(*(string*)(arg));
theFoo.setBar1();
pthread_cleanup_push(&theFoo.cleanBar1,NULL); //what is the correct way to
theFoo.setBar2();
pthread_cleanup_push(&theFoo.cleanBar2,NULL); //pass clean functions?
sleep(100);
pthread_cleanup_pop(1);
pthread_cleanup_pop(1);
return NULL;
}
int main(){
string biryani="biryani";
string pappu="pappu";
pthread_t makeBirayani, makePappu;
pthread_create(&makeBiryani,NULL,&myPThread,(void*)&biryani);
pthread_create(&makePappu,NULL,&myPThread,(void*)&pappu);
pthread_join(makeBiryani,NULL);
pthread_join(makePappu,NULL);
return 0;
}
我避免了编译时错误 ISO C ++禁止使用(void(*)(void*))&Foo::cleanBar1
作为绑定成员函数的地址来形成指向成员函数的指针 pthread_cleanup_push()的参数。但是多线程发生运行时错误(分段错误),因为它在确定清理函数所属的实例时存在不明确性。在这种情况下如何调用here之类的成员函数?语法是什么?
答案 0 :(得分:3)
Foo::cleanBar1
和Foo::cleanBar2
是非静态成员函数,这意味着它们采用隐式的第一个参数,指向必须调用它们的Foo
实例的指针({ {1}}指针)。因此,您无法将指向成员函数的指针传递给this
并获得所需的行为。
您需要创建一个调用所需成员函数的调度程序函数,然后将指向该函数的指针传递给pthread_cleanup_push
。此调度函数可以是自由函数,也可以是pthread_cleanup_push
的{{1}}成员函数。例如,
static
然后将其传递给Foo
class Foo{
public:
Foo(string name):name(name){}
void setBar1(){bar1=malloc(4);sleep(20);}
void cleanBar1(){free(bar1);}
static void bar1_callback(void *arg)
{
static_cast<Foo*>(arg)->cleanBar1();
}
// ..
private:
string name;
void* bar1;
void* bar2;
};
现在对pthread_cleanup_push
的调用将执行pthread_cleanup_push(&Foo::bar1_callback, &theFoo);
并向其传递指向pthread_cleanup_pop
实例的指针,然后该实例将调用Foo::bar1_callback
成员函数。
答案 1 :(得分:0)
根据我对pthread函数pthread_cleanup_push
函数的理解,你可以将一个自由函数的地址(或者可能static
的地址传递给类Foo
)和一个指向对象的指针然后将呼叫路由到正确的成员。
void clean_bar_1(void* arg)
{
Foo* p = static_cast<Foo*>(arg);
p->cleanBar1();
}
然后在myPThread
函数:
pthread_cleanup_push(&clean_bar_1, &theFoo);
重复cleanBar2
方法。
答案 2 :(得分:0)
成员函数需要知道执行它的对象。这就是标准不允许这种直接参考的原因。
只需使用lambda-wrapper,如:
pthread_cleanup_push( [](void*a)->void { reinterpret_cast<Foo*>(a)->cleanBar1(NULL);},
&theFoo); //&theFoo will be passed as argument to the function
但是,当调用清理时,你必须确保你的theFoo对象仍然存在,因为你在推送清理函数时给它的地址,这个地址稍后将被用作lambda函数清理的参数。