I am in trouble with the usage of a template function with POSIX threading.
As a programming language, I am using C++98, and as a threading infrastructure, I am using POSIX threading (<pthread.h>
).
My environment does not support the standard threading (<thread>
)
Normally, we can pass parameters to pthreads as below:
#include <stdio.h>
#include <pthread.h>
void * hello(void *input) {
printf("%s\n", (char *)input);
pthread_exit(NULL);
}
int main(void) {
pthread_t tid;
pthread_create(&tid, NULL, hello, "hello world");
pthread_join(tid, NULL);
return 0;
}
The question is, how can I pass a template function and parameters to pthreads?
Here is the sample template function:
#include <pthread.h>
template<class T>
void *hello(T val){
SampleInterface *interface = &T;
cout << interface->Message<<endl;
}
int main(void) {
pthread_t tid;
SampleClass sClass;
pthread_create(&tid, NULL, hello, sClass);
pthread_join(tid, NULL);
return 0;
}
If I use the above usage, I receive two errors:
error: no matches converting function 'hello' to type 'void* (*)(void*)'
error: candidates are: template<class T> void* hello(T)
Since you are not calling hello()
directly, the compiler can't deduce the template parameter for you, so you have to specify the template parameter explicitly.
You also need to change hello()
to match the signature that pthread_create()
is expecting (like your non-template example does), unless you type-cast the function at the point where you pass it to pthread_create()
(which I don't recommend doing, as it is technically undefined behavior, but it does work in some compilers).
Try this:
#include <iostream>
#include <pthread.h>
template<class T>
void *hello(void *arg){
T *val = static_cast<T*>(arg);
SampleInterface *interface = val;
cout << interface->Message << endl;
return NULL;
}
int main(void) {
pthread_t tid;
SampleClass sClass;
pthread_create(&tid, NULL, hello<SampleClass>, &sClass);
pthread_join(tid, NULL);
return 0;
}
Or:
#include <iostream>
#include <pthread.h>
typedef void* (*pthread_callback_t)(void*);
template<class T>
void *hello(T *val){
SampleInterface *interface = val;
cout << interface->Message << endl;
return NULL;
}
int main(void) {
pthread_t tid;
SampleClass sClass;
pthread_create(&tid, NULL, reinterpret_cast<pthread_callback_t>(hello<SampleClass>), &sClass);
pthread_join(tid, NULL);
return 0;
}
Alternatively, you don't really need the template in your example at all, so you can simplify the code a little:
#include <iostream>
#include <pthread.h>
void *hello(void *arg){
SampleInterface *interface = static_cast<SampleInterface*>(arg);
cout << interface->Message << endl;
return NULL;
}
int main(void) {
pthread_t tid;
SampleClass sClass;
SampleInterface *interface = &sClass;
pthread_create(&tid, NULL, hello, interface);
pthread_join(tid, NULL);
return 0;
}
Or:
#include <iostream>
#include <pthread.h>
typedef void* (*pthread_callback_t)(void*);
void *hello(SampleInterface *interface){
cout << interface->Message << endl;
return NULL;
}
int main(void) {
pthread_t tid;
SampleClass sClass;
SampleInterface *interface = &sClass;
pthread_create(&tid, NULL, reinterpret_cast<pthread_callback_t>(hello), interface);
pthread_join(tid, NULL);
return 0;
}