【问题标题】:Calling a class member function from a thread using pthread_create使用 pthread_create 从线程调用类成员函数
【发布时间】:2016-10-22 17:13:18
【问题描述】:

下面是代码

#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*, void*()(void), void*)'

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

【问题讨论】:

  • 不,你不能那样做。 Posix 线程对 C++ 一无所知。为什么不使用 std::thread?
  • 我的意思是,不能直接di。当然,您可以从符合 Posix 的线程回调中调用您的成员函数。

标签: c++ multithreading


【解决方案1】:

您不能将指向成员函数的指针用作线程例程。考虑使用 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);

【讨论】:

    【解决方案2】:

    您可以通过相应地分派工作的函数来做到这一点:

    #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);
    }
    

    Live example

    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();
    }
    

    Live example

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-01-27
        • 1970-01-01
        • 2020-12-04
        • 2013-12-19
        相关资源
        最近更新 更多