I'm a beginner to pthreads so bear with me. I'm trying to pass a string to the thread_routine1
function. It takes a void pointer as an argument. I then want to print it out.
void *thread_routine1(void *arg1){
cout << arg1 << endl;
pthread_exit(NULL);
}
int main ()
{
pthread_t thread1;
string t1 = "hello", t2 = "world";
pthread_create(&thread1, NULL,thread_routine1, (void *) t1);
pthread_join(thread1, NULL);
return 0;
}
In the pthread_creat function I'm attempting to pass the string but I'm getting a invalid cast type from string to void pointer. I understand I'm probably goin wrong in more than one place so I would appreciate some pointers.
For cases where multiple arguments must be passed, this limitation is easily overcome by creating a structure which contains all of the arguments, and then passing a pointer to that structure in the pthread_create() routine. All arguments must be passed by reference and cast to (void *).
Your thread can access this struct by passing a pointer through the fourth argument of pthread_create() . Create a pointer to your struct as illustrated in the last exercise and do so. struct struct_name* arg_ptr = (struct struct_name*) args; printf("thread arg1: %d\n", arg_ptr->arg1);
The last parameter of pthread_create() is passed as the argument to the function, whereas the return value is passed using pthread_exit() and pthread_join() .
The pthread_join() function waits for a thread to terminate, detaches the thread, then returns the threads exit status. If the status parameter is NULL, the threads exit status is not returned.
This has nothing to do with pthreads, really. You do this cast (void *) t1
, which is essentially taking a sledgehammer onto the type system.
A string in C++ is not a pointer, so casting it to - and treating it as - one is only going to cause undefined behavior.
This is one reason why a C-style cast is to be avoided, because had you done it with a static_cast<void*>(t1)
you'd have gotten a proper error, scolding you for doing something you shouldn't be doing.
Now, if you can't use std::thread
for all its abstractions, and must contend with the pthreads C API, the way to go is to pass the address of t1
. I.e.
pthread_create(&thread1, NULL,thread_routine1, &t1);
And now you don't even need a cast, because you are working with the type system. An object pointer is implicitly convertible to void*
. Well-designed code should not be peppered with casts. They should be infrequent and for a good reason only. Furthermore, a cast should never be written just to "make it compile".
Oh, and don't forget to cast back in your thread function. Now you have a good reason, and the code will be correct with a simple static cast:
void *thread_routine1(void *arg1){
cout << *static_cast<string*>(arg1) << endl;
pthread_exit(NULL);
return nullptr; // The function's return type is `void*`, not `void`! Do not omit a return statement.
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With