I am testing different ways of executing as a thread a function defined in a C ++ class using pthread_create.
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.
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):
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:
#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:
pthread_create()
because there is already a nice wrapper with 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.
So, this is what I got after rewriting OPs code in C++:
#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:
Parent is running.
Hello from ThRoutine2 thread. Number = 2
Hello from ThRoutine1 thread. Number = 1
Hello from ThRoutine3 thread. Number = 3
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”).
I replaced C-ish printf()
by C++ stream output. Please, note, that C++ stream output is thread-safe. However, composing output with stream operators ( <<
) may cause a mixing of outputs from multiple threads. (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
.
When I was about to replace the sleep()
by std::this_thread::sleep()
I became aware that OP used this as kind of synchronization. Please, note: Time (or delay) is an unreliable synchronization for threads. So, I replaced this with a 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). While implementing I realized that the std::thread::thread() is expressive enough to cover all cases of OP without lambda-adapters.
I thought a while whether it's a reasonable answer to solve OPs issue with pthread_create()
using std::thread
instead. IMHO, it is.
std::thread
is the C++ wrapper for pthread
s on systems where pthread
is supported.
On platforms (eg Windows / Visual Studio) where there is something else than pthread
, the std::thread
will wrap something else. So, the same code can be compiled without any modification.
The techniques OP tried to use feel somehow familiar to me. The reason is that I started Object Oriented Programming in C (a long time ago) and switched to C++ later. 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).
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.