简体   繁体   English

C ++ class的成员function使用pthread_create的几种方法:function有输入参数时出错

[英]Several ways to use pthread_create with a member function of a C ++ class: Error when function has input parameter

I am testing different ways of executing as a thread a function defined in a C ++ class using pthread_create.我正在使用 pthread_create 测试在 C ++ class 中定义的 function 作为线程执行的不同方式。

The program that I attach as an example compile and works correctly in these cases:我作为示例附加的程序在这些情况下编译并正常工作:

  • If the function is static: ThRoutine1如果function是static:ThRoutine1
  • If the function is friend: ThRoutine2如果 function 是朋友:ThRoutine2
  • If the function is neither static nor friend and has no parameters, an intermediate function can be used: runThRoutine3 and ThRoutine3如果 function 既不是 static 也不是 friend 并且没有参数,则可以使用中间 function:runThRoutine3 和 ThRoutine3

I compile the program with the command:我用命令编译程序:

g ++ -Wall -g example_program.cpp -lpthread -o example_program

However, I can not create a thread with the ThRoutine4 function that is neither static nor friend and has an input parameter.但是,我无法使用 ThRoutine4 function 创建线程,它既不是 static 也不是朋友,并且有一个输入参数。

After reading several posts on various forums, I have tried to define the s_param structure and the unThRoutine4 function, but when compiling the program I get these errors (it is necessary to uncomment the lines that appear commented):在阅读了各种论坛上的几篇帖子后,我尝试定义 s_param 结构和 unThRoutine4 function,但是在编译程序时出现这些错误(有必要取消注释显示的行):

example_program.cpp: In static member function ‘static void * MyClass :: runThRoutine4 (void *)’:
example_program.cpp: 44: 34: error: ‘class MyClass’ has no member named ‘ptr’
       return ((MyClass *) bundle) -> ptr-> ThRoutine4 (bundle-> number);
                                  ^
example_program.cpp: 44: 56: error: ‘void *’ is not a pointer-to-object type
       return ((MyClass *) bundle) -> ptr-> ThRoutine4 (bundle-> number);

I appreciate any help in this regard.我感谢在这方面的任何帮助。

The source code of example_program.cpp is: example_program.cpp 的源代码为:

#include <pthread.h>
#include <stdio.h>
#include <unistd.h>

#define _REENTRANT


typedef void* (*THREAD_FUNC_PTR)(void *);

struct s_param
{
  void  *ptr;
  int   number;
};

class MyClass
{
  public:
    static void *ThRoutine1 (int number)
    {
      printf("Hello form ThRoutine1 theard. Number = %d\n", number);
    }

    friend void *ThRoutine2 (int number);

    void *ThRoutine3 ()
    {
      printf("Hello form ThRoutine3 theard.\n");
    }

    static void *runThRoutine3 (void *context)
    {
        return ((MyClass *)context)->ThRoutine3();
    }

    void *ThRoutine4 (int number)
    {
      printf("Hello form ThRoutine4 theard. Number = %d\n", number);
    }

    // It is necessary to uncomment this function to get the indicated errors.
    //
    // static void *runThRoutine4(void *bundle)
    // {
    //  return((MyClass *)bundle)->ptr->ThRoutine4(bundle->number);
    //}

};



void *ThRoutine2 (int number)
{
  printf("Hello form ThRoutine2 theard. Number = %d\n", number);
}


int main(void)
{
  int t = 1;
  pthread_t tid[4]; // an array to keep track of the threads
  MyClass cppClass;

  pthread_create(&tid[1],NULL,(THREAD_FUNC_PTR)&cppClass.ThRoutine1,(int *)t++);

  pthread_create(&tid[2],NULL,(THREAD_FUNC_PTR)&ThRoutine2,(int *)t++);

  pthread_create(&tid[3], NULL, &MyClass::runThRoutine3, &cppClass);

  // It is necessary to uncomment this source code line to get the indicated errors.
  //
  // pthread_create(&tid[4], NULL, &MyClass::runThRoutine4, &cppClass);


  printf("Parent is running.\n");
  sleep(10);

  return 0;
}

I just was about to fix OPs code but then I stopped and restarted:我正要修复 OPs 代码,但后来我停下来重新启动:

  1. There is a lot of C code which would be done different in C++.有很多 C 代码在 C++ 中会有所不同。
  2. It feels very wrong to fiddle with the pthread_create() because there is already a nice wrapper with std::thread .摆弄pthread_create()感觉很不对劲,因为std::thread已经有了一个很好的包装器。

While fiddling with OPs code I noticed a lot of other weaknesses which even should be an issue in C as well like eg functions with a non- void return type but no return statement in body.在摆弄 OP 代码时,我注意到许多其他弱点,这些弱点甚至应该成为 C 中的一个问题,例如具有非void返回类型但主体中没有return语句的函数。

So, this is what I got after rewriting OPs code in C++:所以,这是我在 C++ 中重写 OP 代码后得到的:

#include <iostream>
#include <sstream>
#include <thread>

class MyClass
{
  public:
    static void ThRoutine1 (int number)
    {
      std::ostringstream out;
      out << "Hello from ThRoutine1 thread. Number = " << number << '\n';
      std::cout << out.str();
    }

    friend void ThRoutine2 (int number);

    void ThRoutine3(int number)
    {
      std::ostringstream out;
      out << "Hello from ThRoutine3 thread. Number = " << number << '\n';
      std::cout << out.str();
    }

#if 0 // Oops. It's nearly identical to ThRoutine3() now...
    void ThRoutine4 (int number)
    {
      std::ostringstream out;
      out << "Hello from ThRoutine4 thread. Number = " << number << '\n';
      std::cout << out.str();
    }
#endif // 0

};

void ThRoutine2 (int number)
{
  std::ostringstream out;
  out << "Hello from ThRoutine2 thread. Number = " << number << '\n';
  std::cout << out.str();
}

int main()
{
  int t = 1;
  std::thread threads[3];
  MyClass cppClass;
  threads[0] = std::thread(&MyClass::ThRoutine1, t++);
  threads[1] = std::thread(&ThRoutine2, t++);
  threads[2] = std::thread(&MyClass::ThRoutine3, &cppClass, t++);
  
  std::cout << "Parent is running.\n";
#if 0 // Waiting a while is not a reliable synchronization...
  sleep(10);
#else // ...but join is:
  for (std::thread &thread : threads) {
    if (thread.joinable()) thread.join();
  }
#endif // 0
}

Output: Output:

Parent is running.
Hello from ThRoutine2 thread. Number = 2
Hello from ThRoutine1 thread. Number = 1
Hello from ThRoutine3 thread. Number = 3

Live Demo on colirucoliru 现场演示

Notes:笔记:

  1. I removed MyClass::ThRoutine4() after I realized that this was already covered by MyClass::ThRoutine3() (which I modified slightly to “follow the general pattern”).在我意识到这已经被 MyClass::ThRoutine3() 覆盖后,我删除了MyClass::ThRoutine4() MyClass::ThRoutine3() (我稍微修改为“遵循一般模式”)。

  2. I replaced C-ish printf() by C++ stream output. Please, note, that C++ stream output is thread-safe.我将 C-ish printf()替换为 C++ stream output。请注意,C++ stream output 是线程安全的。 However, composing output with stream operators ( << ) may cause a mixing of outputs from multiple threads.但是,将 output 与 stream 运算符 ( << ) 组合在一起可能会导致多个线程的输出混合。 (I noticed this in my first version.) This could be fixed by introducing a mutex – or even simpler by pre-composing the output in a std::stringstream . (我在我的第一个版本中注意到了这一点。)这可以通过引入互斥锁来解决——或者通过在std::stringstream中预先组合 output 来更简单。

  3. When I was about to replace the sleep() by std::this_thread::sleep() I became aware that OP used this as kind of synchronization.当我准备用std::this_thread::sleep()替换sleep()时,我意识到 OP 将其用作一种同步。 Please, note: Time (or delay) is an unreliable synchronization for threads.请注意:时间(或延迟)是线程的不可靠同步。 So, I replaced this with a thread::join() .所以,我用thread::join()替换了它。

  4. My original intention was to demonstrate as well how nicely lambdas can be used for adapters (to fit a certain function into a required signature).我的初衷也是为了演示如何将 lambda 用于适配器(将某个 function 放入所需的签名中)。 While implementing I realized that the std::thread::thread() is expressive enough to cover all cases of OP without lambda-adapters.在实现时,我意识到std::thread::thread()的表现力足以涵盖所有没有 lambda 适配器的 OP 情况。


I thought a while whether it's a reasonable answer to solve OPs issue with pthread_create() using std::thread instead.我想了一会儿,用std::thread代替pthread_create()来解决 OP 问题是否是一个合理的答案。 IMHO, it is.恕我直言,是的。

  1. std::thread is the C++ wrapper for pthread s on systems where pthread is supported. std::thread是支持pthread的系统上pthreadC++ 包装器。

  2. On platforms (eg Windows / Visual Studio) where there is something else than pthread , the std::thread will wrap something else.在除pthread以外的平台(例如 Windows / Visual Studio)上, std::thread将包装其他内容。 So, the same code can be compiled without any modification.因此,无需任何修改即可编译相同的代码。

    Live Demo on Compiler Explorer编译器资源管理器上的现场演示

  3. The techniques OP tried to use feel somehow familiar to me. OP 尝试使用的技术对我来说有点熟悉。 The reason is that I started Object Oriented Programming in C (a long time ago) and switched to C++ later.原因是我在C(很久以前)开始Object面向编程,后来转C++。 Thereby, I carried (my) common C techniques into my C++ code and needed a while to switch to more idiomatic C++ code (after realizing that I started to fight against windmills).因此,我将(我的)常用 C 技术带入了我的 C++ 代码,并需要一段时间切换到更惯用的 C++ 代码(在意识到我开始与风车作斗争之后)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM