tags:

views:

1155

answers:

4

Lets say i have a class such as

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

And then i have a vector of c

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

Now i want to create a thread on c.print();

And the Following is Giving me problem

pthread_create(&t1, NULL, &c[0].print, NULL);

Error Ouput: cannot convert ‘void* (tree_item::)(void)’ to ‘void* ()(void)’ for argument ‘3’ to ‘int pthread_create(pthread_t*, const pthread_attr_t*, void* ()(void), void*)’

+1  A: 

You'll have to give pthread_create a function that matches the signature it's looking for. What you're passing won't work.

You can implement whatever static function you like to do this, and it can reference an instance of c and execute what you want in the thread. pthread_create is designed to take not only a function pointer, but a pointer to "context". In this case you just pass it a pointer to an instance of c.

For instance:

static void* execute_print(void* ctx) {
    c* cptr = (c*)ctx;
    cptr->print();
    return NULL;
}


void func() {

    ...

    pthread_create(&t1, NULL, execute_print, &c[0]);

    ...
}
Jared Oberhaus
ooo i see what you mean.. pass it the pointer of c, gotcha.. will implement and try it out
Shahmir Javaid
A: 

My guess would be this is b/c its getting mangled up a bit by C++ b/c your sending it a C++ pointer, not a C function pointer. There is a difference apparently. Try doing a

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

and then sending p.

I've done what your doing with a member function also, but i did it in the class that was using it, and with a static function - which i think made the difference.

Sean
I tried the above but its giving me syntax errors.. Tried to change it around as well... If you would be kind enough to show that using the pthread_create(...) it might be helpfull
Shahmir Javaid
+4  A: 

My favorite way to handle a thread is to encapsulate it inside a C++ object. Here's 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 would just create a subclass of MyThreadClass with the InternalThreadEntry() method implemented to contain your thread's event loop. You'd need to call WaitForInternalThreadToExit() on the thread object before deleting the thread object, of course (and have some mechanism to make sure the thread actually exits, otherwise WaitForInternalThreadToExit() would never return)

Jeremy Friesner
yes. i do this exact same technique. great way to do it..
Sean
That is a great way i can understand the use of the above Virtual Class, But i have much deaper problems..I have threads that spawn off other threads that need to be all put in a vector. And then a recursive loop to go and join all the threads. Im sure i could implement the above to do that as well by calling the wait in the proper place, But il try it to see where i get to
Shahmir Javaid
I'd say if possible, use `boost::thread`.
GMan
+3  A: 

You can't do it the way you've written it because C++ class member functions have a hidden this parameter passed in. pthread_create() has no idea what value of this to use, so if you try to get around the compiler by casting the method to a function pointer of the appropriate type, you'll get a segmetnation fault. You have to use a static class method (which has no this parameter), or a plain ordinary 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);
Adam Rosenfield
would the above work with vectors in the following way:pthread_create(?
Shahmir Javaid
All the above comments are usefull i used a combination from all to solve an issue.. It still dosent does as simple as i was trying to do it... But unfortunatlly i can only mark one as being the correct, Otherwise every one gets the credit..Thanks
Shahmir Javaid