Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

pthread passing object as argument to pthread_create

For the given program ::

void start(void *n){
  Node *obj = (Node *)n;
  cout << obj -> val;
}

int   
main(int argc, char *argv[])
{
  int i,n;
  cin >> n;
  Node *nodeObj;
  nodeObj = new Node[n];
  pthread_t *p = new pthread_t[n];
  for(i=0;i<n;i++){
    pthread_create(&p[i],NULL,start,(void *)(nodeObj[i]));   /*ERROR HERE in arg pass*/
  }                                                                               
  return 0;   
}

I get the following error::

invalid conversion from ‘void ()(void)’ to ‘void* ()(void)’

I basically want to send each of the object NodeObj[0] , NodeObj[1] , NodeObj[2] ... to each of the new threads I create. the start function is where each of the threads start.

like image 605
Shehbaz Jaffer Avatar asked Jun 10 '26 10:06

Shehbaz Jaffer


2 Answers

This will likely do what you want. I just threw it together so I apologize in advance if there are any syntax errors. It addresses your two issues (incorrect third and fourth parameters to pthread_create()) as well as uses RAII for allocation management:

#include <iostream>
#include <vector>

using namespace std;

struct Node
{
    int value;
};

void *start(void* p)
{
    Node* obj = (Node*)p;
    cout << obj->value;
    return NULL;
}

int main(int argc, char *argv[])
{
    int n;
    cin >> n;
    if (n <= 0)
        return EXIT_FAILURE;

    std::vector<Node> nodes(n);
    std::vector<pthread_t> threads(n);
    for (int i=0;i<n;++i)
        pthread_create(threads.data()+i, NULL, &start, nodes.data()+i);

    std::for_each(threads.begin(), threads.end(),
                  [](pthread_t& t) { pthread_join(t, NULL); });

    return EXIT_SUCCESS;
}

C++11 Threads : Their What's For Dinner

I would advise using the C++11 threading classes and objects (thread, mutex, condition_variable, etc) over using raw-pthreads. They really are the bee's knees. Something similar (though with an auto-calculated N) appears below:

#include <iostream>
#include <vector>
#include <thread>
#include <memory>
using namespace std;

struct Node
{
    int value;
    Node() : value() {}

    // member function we're using as thread proc
    void thread_proc(int n)
    {
        value = n;
    }
};

int main(int argc, char *argv[])
{
    // allocate nodes
    vector<Node> nodes(std::max(std::thread::hardware_concurrency()+1, 4U));

    // starts threads
    vector<thread> threads;
    for (int i=0; i<nodes.size(); ++i)
        threads.emplace_back(std::bind(&Node::thread_proc, nodes.data()+i, i+1));

    // wait for all threads to complete.
    for(auto &t : threads)
        t.join();

    // proof we really did hit *our* nodes in the threads.
    for (auto& node : nodes)
        cout << "Node value: " << node.value << endl;

    return EXIT_SUCCESS;
}

Output

Node value: 1
Node value: 2
Node value: 3
Node value: 4
Node value: 5
like image 136
WhozCraig Avatar answered Jun 12 '26 22:06

WhozCraig


The compiler is complaining about argument 3, the start_routine. The start routine (3rd argument to pthread_create) is specified this way: void *(*start_routine)(void *) a pointer to a method, that takes one void pointer (void *) as an argument and returns a void pointer (void *).

Your code is passing a start as the 3rd argument.

void start(void *n){
    ...
}

A mismatch to what the function is declared to take as the 3rd argument.

Changing your start to:

void *start(void *n) {
  return NULL;
}

Will make the error go away. The value returned from the method acts as the exit code of the thread, unless you are calling pthread_exit.

like image 38
Rickard Avatar answered Jun 12 '26 22:06

Rickard