Error while calling function from pthread_create() - c++

I have declared a function in the Class definition inside a header file:
class A
{
public:
...
void* func(void *);
...
}
In a .C file, I've a pointer to the class A's object as ptr.
Now, when i create a pthread:
iret1 = pthread_create(&thread1, NULL, ptr->func, NULL);
It throws an error as:
error: a pointer to a bound function may only be used to call the function.
But when I declare the function func as static, this error doesn't come.
I just want to know a workaround for this as I can't change the function to static since I can't call other non-static members from it.

You can't use non-static member functions as thread functions, or as functions to any non-C++ function expecting a function pointer. The reason is that all non-static member function has a hidden first argument that becomes the this pointer.
In this case it can be solved with a static proxy-function:
class A
{
public:
void* func();
static void* wrapper(void* object)
{ return reinterpret_cast<A*>(object)->func(); }
};
...
A* ptr = new A;
iret1 = pthread_create(&thread1, NULL, &A::wrapper, ptr);
This will create the thread with A::wrapper as the thread function, and pass the instance pointer as argument. The A::wrapper function then uses this argument as a pointer to the instance, and calls the real function.
However, if you have a C++11 capable compiler and standard library, there are much better support for threads:
A myA;
std::thread myThread(&A::func, &myA);
The above object creation creates a thread that will call A::func and pass the hidden first argument to the function as it needs.

Related

Is there a way to pass a member function to pthread_cleanup_push?

I want to know the way to pass a member function to pthread_clean_push. I don't want to declare the cleanup function as static and pass object's reference to it. Below is the scenario
class Foo{
public:
Foo(string name):name(name){};
void setBar1(){bar1=malloc(4);sleep(20);};
void setBar2(){bar2=malloc(10);sleep(50);};
void cleanBar1(void* arg){free(bar1);};
void cleanBar2(void* arg){free(bar2);};
private:
string name;
void* bar1;
void* bar2;
};
void* myPThread(void* arg){
Foo theFoo(*(string*)(arg));
theFoo.setBar1();
pthread_cleanup_push(&theFoo.cleanBar1,NULL); //what is the correct way to
theFoo.setBar2();
pthread_cleanup_push(&theFoo.cleanBar2,NULL); //pass clean functions?
sleep(100);
pthread_cleanup_pop(1);
pthread_cleanup_pop(1);
return NULL;
}
int main(){
string biryani="biryani";
string pappu="pappu";
pthread_t makeBirayani, makePappu;
pthread_create(&makeBiryani,NULL,&myPThread,(void*)&biryani);
pthread_create(&makePappu,NULL,&myPThread,(void*)&pappu);
pthread_join(makeBiryani,NULL);
pthread_join(makePappu,NULL);
return 0;
}
I avoided compile-time error ISO C++ forbids taking the address of a bound member function to form a pointer to member function by using (void(*)(void*))&Foo::cleanBar1 as the argument to pthread_cleanup_push(). But run-time error(segmentation fault) occurs with multiple threads as it has ambiguity in determining the instance to which the cleanup function belongs. How to invoke the member function like here in this scenario? What is the syntax?
Foo::cleanBar1 and Foo::cleanBar2 are non-static member functions, which means that they take an implicit first argument, a pointer to the Foo instance on which they must be invoked (the this pointer). So you cannot pass a pointer to member function to pthread_cleanup_push and get the desired behavior.
You'll need to create a dispatcher function that calls the member function you want, and then pass a pointer to that function to pthread_cleanup_push. This dispatch function could either be a free function, or a static member function of Foo. For instance,
class Foo{
public:
Foo(string name):name(name){}
void setBar1(){bar1=malloc(4);sleep(20);}
void cleanBar1(){free(bar1);}
static void bar1_callback(void *arg)
{
static_cast<Foo*>(arg)->cleanBar1();
}
// ..
private:
string name;
void* bar1;
void* bar2;
};
And then pass it to pthread_cleanup_push as
pthread_cleanup_push(&Foo::bar1_callback, &theFoo);
Now the call to pthread_cleanup_pop will execute Foo::bar1_callback and pass it a pointer to the theFoo instance, which will then invoke the cleanBar1() member function.
The member function needs to know the object for which it is executed. This is why the standard doesn't allow this direct reference.
Just use a lambda-wrapper, like:
pthread_cleanup_push( [](void*a)->void { reinterpret_cast<Foo*>(a)->cleanBar1(NULL);},
&theFoo); //&theFoo will be passed as argument to the function
However you MUST ensure that your theFoo object still exist when the cleanup is called, because you give its adress when you push the cleanup function, and this address will later be used as argument for the cleanup by the lambda function.
From my understanding of the pthread function pthread_cleanup_push function you can pass the address of a free function (or possibly static to the class Foo) to it and a pointer to an object and then route the call to the correct member.
void clean_bar_1(void* arg)
{
Foo* p = static_cast<Foo*>(arg);
p->cleanBar1();
}
And then in myPThread function:
pthread_cleanup_push(&clean_bar_1, &theFoo);
And repeat for the cleanBar2 method.

Function pointer as a member of a class

What's the difference between a class function and global function with regard to function pointers in C++? I'm asking as the Windows CreateThread method doesn't seem to accept the function that the thread code goes in if the function is a class member.
I can pass the function (that the thread code goes in) to the CreateThread message when it is a global method, but once I make it a member of a class I get the error "argument of type [method layout] is incompatible with parameter of type LPTHREAD_START_ROUTINE". ClassName::* is in the middle now; is this affecting it?
What is the way around this?
Member function pointers (DWORD(WINAPI Foo::*)(LPVOID)) are different types than function pointers (DWORD(WINAPI *)(LPVOID)). Member functions have a hidden this parameter, causing a signature mismatch.
The easiest way to do this is to use C++11's <thread> header:
struct Foo {
void threadProc() {}
};
int main() {
Foo foo;
std::thread t{&Foo::threadProc, foo, /*other arguments to threadProc*/};
t.join();
}
If you have to resort to CreateThread, make use of the void * parameter to pass the instance:
struct Foo {
DWORD threadProc() {...}
};
extern "C" DWORD WINAPI proxyThreadProc(LPVOID userData) {
auto foo = static_cast<Foo *>(userData);
if (foo) {foo->threadProc();}
}
int main() {
Foo foo;
CreateThread(..., proxyThreadProc, &foo, ...);
}
The one in your class can now be pretty much whatever you want (like a std::function) and still work, as long as it's called with the right arguments from within the proxy procedure.
yeah, as #chris said there is a hidden pointer of this which will be connected by the end of parameters. when the thread carry out that, it don't know to match with a pointer in the position of the last parameter, then it failed to recover the heap of this function when finished, so It's banned to use non-static member function of class to drive a thread function except for the global function or static member function of class.

c++ error: invalid use of member 'calls_object::OBJECT' in static member function

I got the following error from the code below.
error: invalid use of member 'calls_object::OBJECT' in static member function|
error: from this location
from the line OBJECT->call(); line 29.
Basically the function must be static because its really a simplified version of the code
which creates a windows thread. I just can't seem to use pointers within a static function but I can create the object within the static function no problem. Is there another way?
CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)windowsthread, (LPVOID)i, NULL, &m_id);
static DWORD_PTR WINAPI windowsthread()
{
OBJECT->call();
}
l
class object
{
private:
public:
object(){}
~object(){}
void call(){}
};
class calls_object
{
private:
object* OBJECT;
public:
calls_object()
{
OBJECT = new object();
}
~calls_object(){}
#ifdef _WIN32
static void windows_function()
{
OBJECT->call();
}
#endif
};
int main()
{
calls_object O;
}
This function:
static void windows_function()
{
OBJECT->call();
}
Is declared as static. It means it does not receive an implicit this pointers: in other words, it does not operate on an instance of calls_object. Therefore, it cannot see the OBJECT member variable.
Either declare the function as non-static, or declare OBJECT as a static member variable (whatever makes more sense in your application).
Basically the function must be static because its really a simplified version of the code which creates a windows thread
Since you are (unfortunately) dealing with a function (CreateThread) that accepts a function pointer, you cannot even use std::bind. However, CreateThread lets you provide a function which accepts a pointer (to void, see the prototype of ThreadProc).
Just pass a pointer to an object as the fourth argument to CreateThread, and let windowsFunction(void*) receive that pointer. Inside windowsFunction(), which would still be static or global (in fact, you do not need the calls_object class at all), you can cast that pointer to a pointer to object and invoke call() on it.
Also notice, that your class calls_object is leaking memory, since you are forgetting to delete the pointer you created in calls_object's constructor:
~calls_object()
{
delete object; // DON'T FORGET THIS!
}
windows_function is a static member function, so is not associated with any calls_object object. OBJECT is a non-static data member, so is associated with a calls_object object. You cannot access a non-static data member from a data member.
Simply make the function non-static and it will work.
Think of it this way. If you didn't even create an object of type calls_object and your main function was just:
int main()
{
calls_object::windows_function();
}
Where would you expect this function to get OBJECT from? Since OBJECT is a non-static member, it only exists as part of a calls_object object. A static member function cannot simply pull OBJECT from nowhere.

How can I pass method pointer as a function parameter in C++ while using pthreads

I have a question related with C++ and threads.
I am more familiar with Java than C++ and this error is confusing me.
Imagine that in x.h file I have a class such as:
class A{
public A();
public virtual void* func(void*);
public virtual void func2();
public virtual void func3();
};
In x.cpp file I want to do that:
void* A::func(void*) {
while(....)
func2();
return NULL;
}
void A::func2() {
...some stuff there...
}
void A::func3() {
pthread_t t1;
pthread_create(&t1, NULL, &A::func, NULL);
void* result;
pthread_join(t1,&result);
...some other stuff...
}
The problem is it hangs with the following error:
"error: ISO C++ forbids taking the address of an unqualified or
parenthesized non-static member function to form a pointer to member
function."
What should I do to fix this?
Thanks.
This is a lousy error message, but fundamentally what it's trying to tell you is that you can't form a function pointer from an instance method (I'm not sure what Java's terminology here is). This is because to call an instance method you need both the address of the actual code and the address of an object to be this, and a regular function pointer only stores the former.
What you need here is a static wrapper method which matches pthread_create's expectations of the thread start routine. You pass this as the fourth argument to pthread_create, and the wrapper converts its argument back to an object pointer and invokes func. This type of wrapper is commonly known as a "thunk", since it adapts one calling convention to another.
class A {
// ...
static void* thread_start_thunk(void* self);
};
void*
A::thread_start_thunk(void* self)
{
return static_cast<A*>(self)->func();
}
// ...
void
A::func3()
{
// ....
pthread_create(&t1, 0, &A::thread_start_thunk, static_cast<void*>(this));
// ...
}
The casts are unavoidable.
You can not just pass a pointer to a method to the thread. That method-pointer alone would not mean anything, because it does not know which instance it belongs to. If you need to call an instance method in a different thread, add a private static method to the class and pass it's address to the thread, along with a pointer to the instance as an argument.
That static method could look somewhat like this:
class A
{
public: virtual void threadMethod();
public:
static void staticThreadMethod(void* instanceObj)
{
((A*)instanceObj)->threadMethod();
}
};
I did not test that code and it obviously does not check for errors, but this is how I usually do it.
use one of:
boost::thread
C++11
some other C++ library threads (a plenty of them)
add a static method to your class, then pass its address to pthread_create w/ user provided void* to pair of your class instance (pointer/ref) and class::*method you want to call. then in static function just call desired method using instance and method address obtained from parameter
In pthread_create(&t1, NULL, &func, NULL); you try to take the address of a member function. There are two issues with that
The correct form is
&A::func
this is what the compiler tries to tell you.
pthread_create wants a pointer to function, not a pointer to a non-static member function. What you can do instead is, creating a static member function and passing the address of this static member function as an argument to pthread_create.
Example:
class A {
public:
static void *func(void *);
};
pthread_t t1;
pthread_create(&t1, NULL, &A::func, NULL);

c++ thread issue

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
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);
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:
pointer to a class method (don't confuse them with function pointers)
pointer to an object
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.
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.