[英]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:我作为示例附加的程序在这些情况下编译并正常工作:
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 代码,但后来我停下来重新启动:
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:笔记:
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()
(我稍微修改为“遵循一般模式”)。
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 来更简单。
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()替换了它。
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.恕我直言,是的。
std::thread
is the C++ wrapper for pthread
s on systems where pthread
is supported. std::thread
是支持pthread
的系统上pthread
的C++ 包装器。
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.因此,无需任何修改即可编译相同的代码。
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.