pthread passing object as argument to pthread_create
Solution 1
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
Solution 2
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
.
Solution 3
The linux manual page for pthread_create() contains a good example.
The thread_start function signature is
void * thread_start(void *arg)
In the main function you can see how to pass arguments (&tinfo[tnum]).
pthread_create(&tinfo[tnum].thread_id, &attr, &thread_start, &tinfo[tnum]);
Note that each thread recieves a distinct set of arguments.
Solution 4
The return type of the thread function must be void *;
void* start(void *n)
{
//Code
}
Secondly, you must send the argument to the function this way:
pthread_create(&p[i],NULL,start,(void *)(&nodeObj[i]));
The requirement of argument passing is that the passed object must be a pointer to something. Even though nodeObj is a pointer, when you use array notation like nodeObj[i] you dereference it. Hence use the ampersand. &nodeObj[i];
You can also simply use (nodeObj+i);
Shehbaz Jaffer
Updated on June 04, 2022Comments
-
Shehbaz Jaffer about 2 years
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.