Pthread function from class

Say I have a class like

class c { // ... void *print(void *){ cout << "Hello"; } } 

And then I have a vector c

 vector<c> classes; pthread_t t1; classes.push_back(c()); classes.push_back(c()); 

Now I want to create a stream on c.print();

Below is the following problem: pthread_create(&t1, NULL, &c[0].print, NULL);

Ouput error: cannot convert 'void * (tree_item: :) (void) to' void * () (void) for the argument '3 to' int pthread_create (pthread_t *, const pthread_attr_t *, void * () (void), void *)

+77
c ++ pthreads
. Jul 20 '09 at 3:14
source share
7 answers

You cannot do this the way you wrote it, because C ++ class member functions have a hidden this parameter passed to. pthread_create() does not know what this value to use, so if you try to bypass the compiler by dropping the method to the function pointer of the corresponding type, you will get a segmetnation error. You should use a static class method (which does not have this parameter) or a regular function to bootstrap the class:

 class C { public: void *hello(void) { std::cout << "Hello, world!" << std::endl; return 0; } static void *hello_helper(void *context) { return ((C *)context)->hello(); } }; ... C c; pthread_t t; pthread_create(&t, NULL, &C::hello_helper, &c); 
+142
Jul 20 '09 at 3:52
source share

My favorite way to handle a stream is to encapsulate it inside a C ++ object. Here is an example:

 class MyThreadClass { public: MyThreadClass() {/* empty */} virtual ~MyThreadClass() {/* empty */} /** Returns true if the thread was successfully started, false if there was an error starting the thread */ bool StartInternalThread() { return (pthread_create(&_thread, NULL, InternalThreadEntryFunc, this) == 0); } /** Will not return until the internal thread has exited. */ void WaitForInternalThreadToExit() { (void) pthread_join(_thread, NULL); } protected: /** Implement this method in your subclass with the code you want your thread to run. */ virtual void InternalThreadEntry() = 0; private: static void * InternalThreadEntryFunc(void * This) {((MyThreadClass *)This)->InternalThreadEntry(); return NULL;} pthread_t _thread; }; 

To use it, you simply subclass MyThreadClass using the InternalThreadEntry () method, which will contain your thread's event loop. Of course, you will need to call WaitForInternalThreadToExit () on the thread object before deleting the thread object (and have some mechanism to make sure the thread is really complete, otherwise WaitForInternalThreadToExit () will never return)

+79
Jul 20 '09 at 3:38
source share

You need to provide pthread_create function that matches the signature it is looking for. What you go through will not work.

You can implement any static function that you like to do, and it can reference an instance of c and do what you want in the stream. pthread_create intended not only for a pointer to a function, but also a pointer to a "context". In this case, you simply pass it a pointer to an instance of c .

For example:

 static void* execute_print(void* ctx) { c* cptr = (c*)ctx; cptr->print(); return NULL; } void func() { ... pthread_create(&t1, NULL, execute_print, &c[0]); ... } 
+8
Jul 20 '09 at 3:21
source share

The above answers are good, but in my case the 1st approach, which converts the function to static, does not work. I tried to convert the exit code to go into a stream function, but this code had many references to non-static members of the class. The second solution for encapsulating a C ++ object works, but has 3-level shells to start the stream.

I had an alternative solution that uses the existing C ++ construct - the "friend" function, and it worked fine for my case. An example of how I used a β€œfriend” (will use the same example for names, showing how it can be converted to a compact form using a friend)

  class MyThreadClass { public: MyThreadClass() {/* empty */} virtual ~MyThreadClass() {/* empty */} bool Init() { return (pthread_create(&_thread, NULL, &ThreadEntryFunc, this) == 0); } /** Will not return until the internal thread has exited. */ void WaitForThreadToExit() { (void) pthread_join(_thread, NULL); } private: //our friend function that runs the thread task friend void* ThreadEntryFunc(void *); pthread_t _thread; }; //friend is defined outside of class and without any qualifiers void* ThreadEntryFunc(void *obj_param) { MyThreadClass *thr = ((MyThreadClass *)obj_param); //access all the members using thr-> return NULL; } 

Of course, we can use boost :: thread and avoid all of these, but I tried to change the C ++ code so as not to use boost (the code was connected with boost for this purpose)

+2
Jul 17 '15 at 20:21
source share

My first answer is ever in the hope that it will be useful to someone: I am now an old question, but I encountered the same error as the above question, since I am writing the TcpServer class and I was trying to use pthreads. I found this question, and now I understand why this is happening. I ended up with this:

 #include <thread> 

method to start threaded -> void* TcpServer::sockethandler(void* lp) {/*code here*/}

and I call it lambda β†’ std::thread( [=] { sockethandler((void*)csock); } ).detach();

which seems like a clean approach to me.

+1
Aug 30 '16 at 14:35
source share

My assumption would be this: b / c C ++ b / c crippled it a bit by sending it a C ++ pointer, not a C function pointer. There seems to be a difference. Try to do

 (void)(*p)(void) = ((void) *(void)) &c[0].print; //(check my syntax on that cast) 

and then send p.

I also did what I did with the member function, but I did it in the class that used it and with the help of the static function, which, in my opinion, mattered.

-one
Jul 20 '09 at 3:31
source share

C ++: how to pass a class member function to pthread_create ()?

http://thispointer.com/c-how-to-pass-class-member-function-to-pthread_create/

 typedef void * (*THREADFUNCPTR)(void *); class C { // ... void *print(void *) { cout << "Hello"; } } pthread_create(&threadId, NULL, (THREADFUNCPTR) &C::print, NULL); 
-one
Aug 22 '17 at 23:43 on
source share



All Articles