一个类的pthread函数

Ang*_*.47 77 c++ pthreads

假设我有一个类如

class c { 
    // ...
    void *print(void *){ cout << "Hello"; }
}
Run Code Online (Sandbox Code Playgroud)

然后我有一个c的向量

vector<c> classes; pthread_t t1;
classes.push_back(c());
classes.push_back(c());
Run Code Online (Sandbox Code Playgroud)

现在,我想创建一个线程 c.print();

以下是给我以下问题: pthread_create(&t1, NULL, &c[0].print, NULL);

错误输出:无法将'void*(tree_item :: )(void)'转换为'void*()(void)'以将参数'3'转换为'int pthread_create(pthread_t*,const pthread_attr_t*,void*()(void),void*)'

Ada*_*eld 142

您不能按照编写它的方式执行它,因为C++类成员函数this传入了一个隐藏参数. pthread_create()不知道this要使用什么值,所以如果您尝试通过将方法强制转换为函数来绕过编译器适当类型的指针,你会得到一个segmetnation错误.您必须使用静态类方法(没有this参数)或普通的普通函数来引导类:

class C
{
public:
    void *hello(void)
    {
        std::cout << "Hello, world!" << std::endl;
        return 0;
    }

    static void *hello_helper(void *context)
    {
        return ((C *)context)->hello();
    }
};
...
C c;
pthread_t t;
pthread_create(&t, NULL, &C::hello_helper, &c);
Run Code Online (Sandbox Code Playgroud)

  • @AdamRosenfield在链接副词的同时,它在语义上也是完全正确的,但这并不能使它成为好的风格!的xD (2认同)

Jer*_*ner 79

我最喜欢的处理线程的方法是将它封装在C++对象中.这是一个例子:

class MyThreadClass
{
public:
   MyThreadClass() {/* empty */}
   virtual ~MyThreadClass() {/* empty */}

   /** Returns true if the thread was successfully started, false if there was an error starting the thread */
   bool StartInternalThread()
   {
      return (pthread_create(&_thread, NULL, InternalThreadEntryFunc, this) == 0);
   }

   /** Will not return until the internal thread has exited. */
   void WaitForInternalThreadToExit()
   {
      (void) pthread_join(_thread, NULL);
   }

protected:
   /** Implement this method in your subclass with the code you want your thread to run. */
   virtual void InternalThreadEntry() = 0;

private:
   static void * InternalThreadEntryFunc(void * This) {((MyThreadClass *)This)->InternalThreadEntry(); return NULL;}

   pthread_t _thread;
};
Run Code Online (Sandbox Code Playgroud)

要使用它,您只需创建一个MyThreadClass的子类,并实现InternalThreadEntry()方法以包含线程的事件循环.当然,你需要在删除线程对象之前调用线程对象上的WaitForInternalThreadToExit()(并且有一些机制来确保线程实际退出,否则WaitForInternalThreadToExit()永远不会返回)

  • 这个解决方案非常优雅.我将从现在开始使用它.谢谢Jeremy Friesner.+1 (4认同)
  • 我想如果可能的话,使用`boost :: thread`. (2认同)

Jar*_*aus 8

你必须提供pthread_create一个与它正在寻找的签名相匹配的功能.你传递的东西是行不通的.

您可以实现您喜欢的任何静态函数,它可以引用一个实例c并在线程中执行您想要的操作.pthread_create被设计为不仅采用函数指针,而且采用指向"上下文"的指针.在这种情况下,您只需传递一个指向实例的指针c.

例如:

static void* execute_print(void* ctx) {
    c* cptr = (c*)ctx;
    cptr->print();
    return NULL;
}


void func() {

    ...

    pthread_create(&t1, NULL, execute_print, &c[0]);

    ...
}
Run Code Online (Sandbox Code Playgroud)