使用 pthread_create 从线程调用类成员函数

Calling a class member function from a thread using pthread_create

本文关键字:调用 成员 函数 线程 pthread create 使用      更新时间:2023-10-16

下面是代码

#include <iostream>
#include <pthread.h>
using namespace std;
class Base
{
private:
public:
void *threadCall1( void * value)
{
cout<<"inside threadCall1"<<endl;
}
protected:
};
class Derived
{
private:
public:
void  *threadCall2 ();
protected:

};

void *Derived::threadCall2()
{
cout<<"inside threadCall2"<<endl;
}
int main ()
{
int k = 2;
pthread_t t1;
cout<<"inside main"<<endl;
Base *b = new Base();
pthread_create(&t1,NULL,&b->threadCall1,(void *)k);
return 0;
}

错误

main.cc:在函数int main()': main.cc:46: error: ISO C++ forbids taking the address of a bound member function to form a pointer to member function. Say&Base::threadCall1' main.cc:46:错误:不能 将void*(Base::*)(void*)' tovoid*()(void)' 转换为参数3' toint pthread_create(pthread_t*, const pthread_attr_t*, 无效*()(无效),无效*)'

我同意C++禁止此调用,但是有什么方法可以使用posix线程调用类成员函数

您可以通过相应地调度工作的函数来执行此操作:

#include <iostream>
#include <pthread.h>
struct Base {
virtual void work() {
std::cout << "Base::work()n";
}
virtual ~Base() {}
};
struct Derived : public Base {
void work() override {
std::cout << "Derived::work()n";
}
};
void* thread_adapter(void* obj) {
Base* p = static_cast<Base*>(obj);
p->work();
return nullptr;
}
int main() {
Derived d;
pthread_t thread;
pthread_create(&thread, nullptr, thread_adapter, &d);
pthread_join(thread, nullptr);
}

现场示例

pthread_create接受指向线程函数的任意数据的指针。传递对象的地址,并使用转发函数,例如上面定义的thread_adapter。在适配器函数中,可以将参数static_cast回线程函数中的Base*,并根据需要调用成员函数。

但是,您可能希望查看 std::thread 库,它以更自然的方式支持此类操作:

#include <iostream>
#include <thread>
struct Base {
virtual void work() {
std::cout << "Base::work()n";
}
virtual ~Base() {}
};
struct Derived : public Base {
void work() override {
std::cout << "Derived::work()n";
}
};
int main() {
Derived d;
std::thread t(&Base::work, d);
t.join();
}

现场示例

没有&b->threadCall1这样的东西。幸运的是,pthread 允许您将一个空 ptr 传递给类(你用 k 填充的那个)。将b作为此 void ptr 传递给全局(或静态成员)函数,该函数只需调用b->threadCall1();然后将 k 移动到 Base 的属性而不是 Base::threadCall1() 的参数。

不能将指向成员函数的指针用作线程例程。考虑使用 thead 上下文结构将需求信息传递给 thead 例程:

struct thread_context {
Base* object;
void (Base::*func)(void*);
};
void *thread_routine(void *arg) {
thread_context* context = static_cast<thread_context*>(arg);
context->object->(*context->func)(nullptr);
...
}
...
thread_context context = {
b1,
&Base::threadCall1
};
pthread_create(&t1,NULL,&thead_routine, &context);