Reputation: 2101
I'm trying to create a thread in c++ with this code:
pthread_t mythread;
void* f (void*) = MyClass::myfunction;
pthread_create(&mythread, NULL, &f, NULL);
It's not working. Any idea what's wrong ?
myfunction is of type:
void* MyClass::myfunction(void* argv);
The error returned is:
error: declaration of ‘void* Class::f(void*)’ has ‘extern’ and is initialized
error: invalid pure specifier (only ‘= 0’ is allowed) before ‘::’ token
error: function ‘void* Class::f(void*)’ is initialized like a variable
Upvotes: 2
Views: 436
Reputation: 254751
You're declaring f
as a function rather than a function pointer. It should be:
void* (*f) (void*) = &MyClass::myfunction;
^^^^
pthread_create(&mythread, NULL, f, NULL);
^ no & since it's already a pointer
This will also only work if myfunction
is static, since you can't convert a pointer-to-member-function to a pointer-to-function.
If you do need to the thread to execute a non-static member function on a particular object, then one approach is to write a static wrapper taking the object as an argument:
class MyClass {
public:
void start_thread() {
// Pass "this" to the thread we're creating
pthread_create(&mythread, NULL, &MyClass::thread_entry, this);
}
private:
static void * thread_entry(void * object) {
// Call the member function on the object passed to the thread
return static_cast<MyClass*>(object)->thread();
}
void * thread() {
// do the interesting stuff, with access to the member variables
}
};
Of course, these days there's a standard thread library which removes the need for this dance:
std::thread thread(&MyClass::thread, this);
Upvotes: 6
Reputation: 72319
Pthreads expects a function pointer, and with classes, you can only point to a static method using a function pointer.
If you'd like to call a specific method of a class on a specific object, you need two separate parts of data:
These two joined together can be informally called a delegate.
PThreads is a C library, and to interoperate with it, you need a little workaround:
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine)(void*),
void *arg);
We're going to wrap the class method in a static class method, to be able to pass it as parameter start_routine
, and we're going to pass the pointer to the object itself as arg
.
See the code:
struct Foo {
// wrapper method
static void* threadStartingPoint(void* obj) {
return ((Foo)obj)->threadFunc();
}
// your target method itself
void* threadFunc() {
// this is where you do your logic
}
}
Such workaround allows you to use pthread_create(thread, attr, Foo::threadStartingPoint, someObject)
.
Note that if you are lucky enough to have a modern compiler which supports std::thread
, you can use that instead of pthreads and have the code much simpler - you just need to create a std::function
object and pass it to std::thread
's constructor.
Upvotes: 2
Reputation: 7521
You simple can't do what you are trying to do - a member function (UNLESS it is static) needs an object in which to be called - that is the process starting the thread can't just call MyClass::f() because it needs to call something.f() - and it doesn;t know what something is.
Typically one gets around this by defining a static member function which takes the object as a parameter and then calls the member function on that object.
Upvotes: 1