ameerosein
ameerosein

Reputation: 563

How to multithreading a class member function with pthreads?

I'm trying to run a function named extensionStep from a class named SVAnchor in multi threads. i use this code:

 rc = pthread_create(&threads[i], NULL, extensionStep, &td[i]);

to call the function and here is the definition of extensionStep :

void* SVAnchor::extensionStep( void *threadarg)

and i got the following error:

error: cannot convert 'SVAnchor::extensionStep' from type 'void* (SVAnchor::)(void*)' to type 'void* (*)(void*)'
           rc = pthread_create(&threads[i], NULL, extensionStep, &td[i]);
                                                                       ^

that shows the problem is converting from type 'void* (SVAnchor::)(void*)' to type 'void* ()(void)'

How to solve this problem?

Thanks all

Upvotes: 1

Views: 730

Answers (2)

nishantsingh
nishantsingh

Reputation: 4662

This should do the job: (After making the function extensionStep static)

rc = pthread_create(&threads[i], NULL, &(SVAnchor::extensionStep), &td[i]);

Or you can create a wrapper function like this:

struct Argument {
    SVAnchor* ptr;
    int* tid;
}

static void *extensionStepWrapper(void *arg)
{
    return (((Argument*)arg)->ptr)->extensionStep(((Argument*)arg)->tid);
}

And use the wrapper:

Argument arg;
arg.ptr = &(class_variable_name); // Use appropriate name (whatever you variable name is for the object of the class SVAnchor)
arg.tid = &(td[i]);

rc = pthread_create(&threads[i], NULL, &(SVAnchor::extensionStepWrapper), &arg);

Note that if you're calling this from inside another member function, you may do this instead:

arg.ptr = this; 

You can also create a method in the class to start the thread:

bool StartThread(int* tid){
      return (pthread_create(&_thread, NULL, extensionStep, tid) == 0);
}

You might also need to pass the thread as argument of StartThread() function.

Upvotes: 1

user2249683
user2249683

Reputation:

This is a common mapping of a class member function to a C-callback:

#include <iostream>
#include <pthread.h>

class Task
{
    public:
    Task() : thread_id(0) {}

    bool start() {
        // Passing this as user data to the C-callback.
        return pthread_create(&thread_id, 0, invoke, this) == 0;
    }

    void stop() {
        void* no_result;
        pthread_join(thread_id, &no_result);
    }

    private:
    Task(const Task&); // no copy (C++11 delete)
    Task& operator = (const Task&); // no copy (C++11 delete)

    void process() {
        std::cout << "Hello\n";
    }

    // The C-callback has to be static.
    static void* invoke(void* self) {
        // Note: The invocation takes place in start (passing this) 
        static_cast<Task*>(self)->process();
        // No result passed to join.
        return 0;
    }

    pthread_t thread_id;
};

int main() {
    Task task;
    task.start();
    task.stop();
}

This is a C++11 version:

#include <iostream>
#include <thread>

class Task
{
    public:
    void operator () () {
        std::cout << "Hello\n";
    }
};

int main() {
    Task task;
    std::thread thread(task);
    thread.join();
}

Upvotes: 1

Related Questions