I have almost completed an homework assignment where I am required to use pthreads. I have figured out the pthreads. The only problem I have left is figuring out how to pass multiple arguments to threads through pthread_create().
I need to pass two chars to the thread. I have to cast them to (*void) to use with pthread_create(). I can pass them, but I can't figure out how to get the values from *parameter in the function.
void *my_function(void *parameter) {
/* ATTEMPT 1 - DOESN'T WORK */
//char* arguments[2];
//arguments = (char * [2]) parameter;
/*Error message:
error: ISO C++ forbids casting to an array type char* [2] [-fpermissive]
error: incompatible types in assignment of char** to char*[2]
*/
/* ATTEMPT 2 - DOESN'T WORK */
//char *my_data = (char *)parameter;
//my_data is blank when I try to use cout to check it's values
/* What I need to do is get those two chars from the array and print them out as part of this thread function */
pthread_exit(NULL);
}
int main(int argc, char **argv) {
char duration = '5'; //in reality, this value is taken from argv but I am leaving that out for brevity
pthread_t threads[3];
for(int i=0; i < 3; i++){
char thread_args[2] = {i, duration};
//create thread with arguments passed in
int results = pthread_create(&threads[i], NULL, my_function, (void *) &thread_args);
//testing for pthread error
if (results){
printf("ERROR; return code from pthread_create() is %d\n", results);
exit(-1);
}
}
/* Wait for all threads to complete */
for (int j=0; j < num_threads; j++) { // https://computing.llnl.gov/tutorials/pthreads/
pthread_join(threads[j], NULL);
}
/* some information prints here that is unrelated to my problem (the date, time, etc) */
pthread_exit(NULL);
}
I was able to pass one value through with no problem. Any suggestions?
The closest existing question I could find was this but I still am having no luck: Converting from void* to char ** in C
Thank you!
Note that within this loop:
for(int i=0; i < 3; i++){
char thread_args[2] = {i, duration};
int results = pthread_create(&threads[i], NULL, my_function, (void *)
...
}
thread_args is a local array with automatic storage duration, lifetime of which is tied to each iteration so there is a chance that the memory where you store these arguments might be freed before the thread will access it, which would lead to undefined behavior in that case.
Much better approach would be to create a structure, that you would use to pass the data to this thread:
typedef struct {
char duration;
int num;
} ThreadData;
Then your code could look like this:
void *my_function(void *parameter) {
// retrieve and print the thread data:
ThreadData* td = (ThreadData*) parameter;
printf("num = %d, duration = %c\n", td->num, td->duration);
delete td;
return NULL;
}
int main(int argc, char **argv) {
char duration = '5';
pthread_t threads[3];
for (int i = 0; i < 3; i++) {
// create structure that will be passed to thread:
ThreadData* td = new ThreadData;
td->duration = duration;
td->num = i;
//create thread with arguments passed in:
int ret = pthread_create(&threads[i], NULL, my_function, (void *) td);
//testing for pthread error:
if (ret) {
printf("ERROR; return code from pthread_create() is %d\n", ret);
exit(-1);
}
}
// wait for all threads to complete:
for (int i = 0; i < 3; i++) {
pthread_join(threads[i], NULL);
}
exit(0);
}
Also note that to end thread's execution it is better to use return than pthread_exit since with return it is guaranteed that variables within thread's routine will be destroyed and stack will be unwound. For more information see return() versus pthread_exit() in pthread start functions
Related
I want to call a function with multiple threads, and I only need to pass a single integer to that function (the thread id, so if it is accessible I need no value to pass).
How should I do this?
for example like:
for(int i=0; i < numberOfThread; i++ ){
pthread_create(&threads[i], NULL, multichaper, &td[i]);
}
in which multichaper is my function and threadID is an integer.
Update: I marked the answer from user3286661 as the right answer and that worked for me, if you want a more detailed answer you can check my own solution to this question in answers.
General approach to this is to make the function like this:
void* multichaper(void* arg) {
int tid = *(int*)arg;
...
}
And while calling pthread_create:
pthread_create(&threads[i], NULL, multichaper, &td[i])
where td[i] is an int.
You really should consider moving to C++11 threads:
#include <thread>
#include <iostream>
void show_id(int id) {
std::cout << id << std::endl;
}
int main()
{
std::thread t(show_id, 10);
t.join();
}
If you must use pthreads, though:
#include <iostream>
#include <pthread.h>
void *show_id(void *x_void_ptr)
{
const int id = *static_cast<int *>(x_void_ptr);
std::cout << id << std::endl;
return NULL;
}
int main()
{
pthread_t t;
int id = 10;
if(pthread_create(&t, NULL, show_id, &id)) {
std::cerr << "couldn't create" << std::endl;
return -1;
}
if(pthread_join(t, NULL)) {
std::cerr << "couldn't join" << std::endl;
return -2;
}
}
Note how much better the first version is:
No casts
Fewer explicit checks
No problem with the lifetime of the object you're passing - in the first version, you're passing a pointer to it, and thus must ensure it's "alive" while the thread is using it.
No unintuitive void * returns (with the same lifetime problems).
No. You can't do that. The function you pass to pthread_create must have the signature void *(*start_routine) (void *). That is, a function taking a non-const pointer to void and returning a non-const pointer to void.
The simplest way is something like:
int *arg = new int(threadID);
pthread_create(&threads[i], NULL, multichaper, threadID );
and then multichaper looks like:
void *multichaper(void *arg)
{
int *pint = static_cast<int*>(arg);
int threadID = *pint;
delete pint;
...
return nullptr;
}
Note that I have allocated the int on the heap to avoid having to worry about variable lifetimes. If you can guarantee that the variable threadID in the calling function will outlive the thread, then you can skip that bit.
I strongly recommend you use C+11 and the built-in threading library, or if you can't do that, use boost::threads. They both make this much easier!
As i want to pass numbers from 0 to NumberOfThreads to my function i finally used the code below, by passing an integer inside a struct and locking (lock_mutex) that when trying to retrieve the threadNum:
Calling function in multi threads in a member function of SVAnchor class:
pthread_t threads[this->numberOfThread];
pthread_attr_t attr;
params_t params;
pthread_mutex_init (¶ms.mutex , NULL);
pthread_cond_init (¶ms.done, NULL);
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
for(int i=0; i < this->numberOfThread; i++ ){
params.id = i;
params.ptr = this;
rc = pthread_create(&threads[i], NULL, &(SVAnchor::multichaperWrapper), ¶ms);
pthread_cond_wait (¶ms.done, ¶ms.mutex);
}
pthread_attr_destroy(&attr);
void* status;
for(int i=0; i < this->numberOfThread; i++ )
rc = pthread_join(threads[i], &status);
pthread_mutex_destroy (¶ms.mutex);
pthread_cond_destroy (¶ms.done);
with params_t as follows:
struct params {
SVAnchor* ptr;
pthread_mutex_t mutex;
pthread_cond_t done;
int id;
};
typedef struct params params_t;
and then multichaperWrapper is as follows:
void* SVAnchor::multichaperWrapper(void* arg){
return (((params*)arg)->ptr)->multichaper( ((params*)arg));
}
and multichaper is as follows:
void* SVAnchor::multichaper( void *threadarg /*0 <= threadNum < numberofthreads*/ ){
int threadNum;
/* Lock. */
pthread_mutex_lock(&(*(params_t*)(threadarg)).mutex);
/* Work. */
threadNum = (*(params_t*)(threadarg)).id;
/* Unlock and signal completion. */
pthread_mutex_unlock(&(*(params_t*)(threadarg)).mutex);
pthread_cond_signal (&(*(params_t*)(threadarg)).done);
cout<<threadNum<<endl;
...
}
If all you want to do is pass an id to the calling thread you can do so by burying it in the void* parameter, and do so portably. Like,
pthread_create(&threads[i], NULL, multichaper, (void*)threadID );
I have the test code:
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
pthread_t th_worker, th_worker2;
void * worker2(void *data) {
for(int i = 0; i< 1000000; i++){
printf("thread for worker2----%d\n", i);
usleep(500);
}
}
void * worker(void *data){
pthread_create(&th_worker2, NULL, worker2, data);
for(int i = 0; i< 100; i++){
printf("thread for worker-----%d\n", i);
usleep(500);
}
}
void join(pthread_t _th){
pthread_join(_th, NULL);
}
In main() function, If I call join(the_worker2):
int main() {
char* str = "hello thread";
pthread_create(&th_worker, NULL, worker, (void*) str);
/* problem in here */
join(th_worker2);
return 1;
}
--> Segment Fault error
Else, i call:
join(the_worker);
join(th_worker2);
---> OK
Why have segment fault error in above case?
Thanks for help !!!
If you posted all your code, you have a race condition.
main is synchronized with the start of worker but not worker2.
That is, main is trying to join th_worker2 before worker has had a chance to invoke pthread_create and set up th_worker2 with a valid [non-null] value.
So, th_worker2 will be invalid until the second pthread_create completes, but that's already too late for main. It has already fetched th_worker2, which has a NULL value and main will segfault.
When you add the join for th_worker, it works because it guarantees synchronization and no race condition.
To achieve this guarantee without the join, have main do:
int
main()
{
char *str = "hello thread";
pthread_create(&th_worker, NULL, worker, (void *) str);
// give worker enough time to properly start worker2
while (! th_worker2)
usleep(100);
/* problem in here */
join(th_worker2);
return 1;
}
An even better way to do this is to add an extra variable. With this, the first loop is not needed [but I've left it in]:
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
int worker_running;
pthread_t th_worker;
int worker2_running;
pthread_t th_worker2;
void *
worker2(void *data)
{
// tell main we're fully functional
worker2_running = 1;
for (int i = 0; i < 1000000; i++) {
printf("thread for worker2----%d\n", i);
usleep(500);
}
return NULL;
}
void *
worker(void *data)
{
// tell main we're fully functional
worker_running = 1;
pthread_create(&th_worker2, NULL, worker2, data);
for (int i = 0; i < 100; i++) {
printf("thread for worker-----%d\n", i);
usleep(500);
}
return NULL;
}
void
join(pthread_t _th)
{
pthread_join(_th, NULL);
}
int
main()
{
char *str = "hello thread";
pthread_create(&th_worker, NULL, worker, (void *) str);
// give worker enough time to properly start worker2
// NOTE: this not necessarily needed as loop below is better
while (! th_worker2)
usleep(100);
// give worker2 enough time to completely start
while (! worker2_running)
usleep(100);
/* problem in here (not anymore!) */
join(th_worker2);
return 1;
}
Like my title says, I'm trying to modify the CreateThread function. I want it to report the sequence number of the thread using the loop.
I'm fairly new to programming in C++ and am unsure which parameter needs to be altered. I suspect it may be the 'lpParameter' but after looking on microsofts website (https://msdn.microsoft.com/en-us/library/windows/desktop/ms682453%28v=vs.85%29.aspx) I still do not understand how the parameters work.
So far I have:
int int_tmain(int argc, _TCHAR* argv[])
{
HANDLE hThread[numThreads];
int tNum[10];
for (int i = 0; i < numThreads; i++)
{
tNum[i] = i;
hThread[i] =
CreateThread(NULL, 0, helloFun, NULL, 0, NULL);
} WaitForMultipleObjects(numThreads, hThread, TRUE, INFINITE);
return 0;
}
Which produces a blank thread.
EDIT:
Sorry for the confusion guys. I have declared the thread routine:
const int numThreads = 4;
DWORD WINAPI helloFun(LPVOID pArg)
{
printf("Hello Thread \n");
return 0;
}
It's not clear what you are trying to do, but it is clear that you are calling WaitForMultipleObjects in the wrong place.
You are trying to wait for numThreads after only creating one thread. The rest of the hThread array is still uninitialized, and passing wild handles to WaitForMultipleObjects is a terrible idea.
Move the wait call outside the loop.
Your thread routine must be declared
DWORD name (LPVOID whatever)
Whatever is passed as lpParameter is passed to the thread. In this case, cast integer to pointer and back.
As you mentioned, if you want to pass a parameter to the thread, then you use the lpParameter. It expects a pointer, so you could pass, for instance, &i, although that's not exactly a good idea. You could create a pointer to int, and pass it, and then delete after WaitForMultipleObjectsreturns.
As Ben said, you are calling WaitForMultipleObjects in the wrong place.
Something like this should work:
int int_tmain(int argc, _TCHAR* argv[])
{
HANDLE hThread[numThreads];
int tNum[10];
int *parameters[numThreads];
for (int i = 0; i < numThreads; i++)
{
tNum[i] = i;
parameters[i] = new int(i);
hThread[i] = CreateThread(NULL, 0, helloFun, (void *)parameters[i], 0, NULL);
}
WaitForMultipleObjects(numThreads, hThread, TRUE, INFINITE);
for (int i = 0; i < numThreads; i++)
delete parameters[i];
return 0;
}
You will have to cast the lpParameter to int in your helloFun.
Try something more like this:
const int maxThreads = 4;
DWORD WINAPI helloFun(LPVOID pArg)
{
int num = * (int*) pArg;
printf("Hello from Thread %d\n", num);
return 0;
}
int _tmain(int argc, _TCHAR* argv[])
{
HANDLE hThread[maxThreads];
int tNum[maxThreads];
int numThreads = 0;
for (int i = 0; i < maxThreads; i++)
{
tNum[numThreads] = i+1;
hThread[numThreads] = CreateThread(NULL, 0, &helloFun, &tNum[numThreads], 0, NULL);
if (hThread[numThreads] == NULL)
{
printf("Unable to create a thread! Error: %u\n", GetLastError());
break;
}
++numThreads;
}
if (numThreads > 0)
{
WaitForMultipleObjects(numThreads, hThread, TRUE, INFINITE);
for (int i = 0; i < numThreads; i++)
CloseHandle(hThread[i]);
}
return 0;
}
This is the snippet of the code. I am able to set the name of thread. However, I get an error while retrieving the name of the thread. Please help.
void *Thread_Function_A(void *thread_arg)
{
char buf[7];
int rc;
pthread_t self;
self = pthread_self ();
rc = pthread_getname_np(self, buf,7);
if ( rc != 0 )
cout<<"Failed getting the name"<<endl;
}
int main(int argc, char *argv[])
{
int rc;
pid_t thread_pid_val = getpid();
thread_1.create_thread((thread_1.get_thread_id()), NULL,Thread_Function_A,&thread_pid_val);
thread_2.create_thread((thread_2.get_thread_id()), NULL,Thread_Function_A,&thread_pid_val);
rc = pthread_setname_np(*(thread_1.get_thread_id()), "Thread_A");
if( rc != 0)
{
cout<<"Setting name for thread A failed"<<endl;
}
rc = pthread_setname_np(*(thread_2.get_thread_id()), "Thread_B");
if( rc != 0)
{
cout<<"Setting name for thread B failed"<<endl;
}
pthread_join( *(thread_1.get_thread_id()), NULL);
pthread_join( *(thread_2.get_thread_id()), NULL);
return 0;
}
output : -
$./thread_basic.out
Failed getting the nameFailed getting the name
The name of thread is The name of thread is
The strerror says - Numerical result out of range
error =34
Added now complete code. Here, I don't get the right name set. Instead, it retrieves the name of the program.
void *Thread_Function_A(void *thread_arg)
{
char name[300];
char buf[200];
int rc;
char message[100];
FILE *fp;
pthread_t self;
self = pthread_self ();
rc = pthread_getname_np(self, buf,200);
if ( rc != 0 )
{
cout<<"Failed getting the name"<<endl;
cerr<<"Pthread get name error ="<<rc<< " " << strerror(rc) << endl;
}
sprintf(name,"log_%s.txt",buf);
cout<<"The name of thread is "<<buf<<endl;
fp = fopen(name,"w+");
for( int i = 1; i<=5; i++)
{
sprintf(message,"The thread id is %d and value of i is %d",pthread_self(),i);
fprintf(fp,"%s\n", message);
fflush(fp);
/** local variable will not be shared actually**/
/** each thread should execute the loop for 5 **/
/** total prints should be 10 **/
}
pthread_exit(NULL);
}
int main(int argc, char *argv[])
{
int rc;
pthread_t threadA, threadB;
pid_t thread_pid_val = getpid();
thread_1.create_thread(&threadA, NULL,Thread_Function_A,&thread_pid_val);
thread_1.set_thread_id(threadA);
rc = pthread_setname_np(threadA, "Thread_A");
if( rc != 0)
{
cout<<"Setting name for thread A failed"<<endl;
}
thread_2.create_thread(&threadB, NULL,Thread_Function_A,&thread_pid_val);
thread_2.set_thread_id(threadB);
rc = pthread_setname_np(threadB, "Thread_B");
if( rc != 0)
{
cout<<"Setting name for thread B failed"<<endl;
}
pthread_join( threadA, NULL);
pthread_join( threadB, NULL);
return 0;
}
The output is the following.
]$ ./thread_basic.out
The name of thread is thread_basic.ou
The name of thread is Thread_B
In addition to the race condition, which won't make your call fail but may not return what you want, this is why the call fails.
man 3 pthread_getname_np
The pthread_getname_np() function can be used to retrieve the name of the thread. The thread argument specifies the thread whose name is to be retrieved. The buffer name is used to return the thread name; len specifies the number of bytes available in name. The buffer specified by name should be at least 16 characters in length. The returned thread name in the output buffer will be null terminated.
char buf[7];
is going to fail.
You are using a mix of C and C++ features which you should avoid, and with parts of code that we can't verify, e.g your method get_thread_id. But the problem of your code is obvious, you are trying to obtain the the names of the threads far too early: your main has not the slightest chance to place the names before the threads are already terminated.
Also, your thread function is not correct, and any compiler with a minimum level of warning should have told you. A function with a non-void return type needs a return statement. In C this would only lead to undefined behavior if you'd use the return value of the function, which you can't know since it is the thread library which calls your function.
I am using pthread + ACE to write a fake client.
this client has 3 threads, and each thread could send and receive message endlessly by using ACE. however, these threads always be halted by the function send() or recv(). that is, the thread would exit if there is something wrong with sending or receiving, unfortunately, I don't know what is the error, and I could not catch it, too. the codes are:
struct thread_data {
int thread_id;
string ip;
uint32_t port;
uint32_t timeout;
};
std::vector<struct thread_data> m_thread;
void * test_fun1(void * threadid)
{
struct thread_data * tmp_thread_data = (struct thread_data *)threadid;
long tmp_threadid = (long)tmp_thread_data->thread_id;
string tmp_ip = tmp_thread_data->ip;
uint32_t tmp_port = tmp_thread_data->port;
uint32_t tmp_timeout = tmp_thread_data->timeout;
ACE_INET_Addr addr(tmp_port, tmp_ip.c_str());
ACE_Time_Value timeout(0, tmp_timeout * 1000);
ACE_SOCK_Connector connector;
ACE_SOCK_Stream peer;
// connect
if(connector.connect(peer, addr, &timeout) != 0)
pthread_exit((void *) threadid);
// send msg
while (1)
{
ssize_t tmp_ret1 = peer.send("hello world", 12);
if (tmp_ret1 <= 0)
continue;
char tmp_buf[1024] = '\0';
ssize_t tmp_ret2 = peer.recv(tmp_buf, 1024, &timeout);
if (tmp_ret2 <= 0)
continue;
else
fprintf(stderr, "recv:%s\n", tmp_buf);
}
// close
peer.close();
pthread_exit((void *) threadid);
}
int main(int argc, char *argv[])
{
std::vector<pthread_t> threads;
pthread_attr_t attr;
int rc;
int i = 0;
void * status;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
// thread create
int tmp_num = 3;
for(i = 0; i < tmp_num; i++)
{
pthread_t tmp_thread_handler;
struct thread_data tmp_thread_info;
tmp_thread_info.thread_id = i;
tmp_thread_info.ip = "127.0.0.1";
tmp_thread_info.port = 8001;
tmp_thread_info.timeout = 100;
rc = pthread_create(&tmp_thread_handler, NULL, test_fun1, (void *)&tmp_thread_info);
if (rc != 0)
return -1;
threads.push_back(tmp_thread_handler);
m_thread.push_back(tmp_thread_info);
}
// thread start
pthread_attr_destroy(&attr);
for(i = 0; i < tmp_num; i++)
{
rc = pthread_join(threads[i], &status);
if (rc != 0)
return -1;
}
pthread_exit(NULL);
return 0;
}
what should I do if I want to send and receive message endlessly? any help would be appreciated!
You have a significant scope-lifetime issue in this code. You're sending a data block to your threads that is created/destroyed with each loop iteration. Leaving out the side-lines:
// thread create
int tmp_num = 3;
for(i = 0; i < tmp_num; i++)
{
pthread_t tmp_thread_handler;
struct thread_data tmp_thread_info;
// --- snip ----
rc = pthread_create(&tmp_thread_handler, NULL, test_fun1, (void *)&tmp_thread_info);
// --- snip ----
}
Whether the resulting block is copied into the underlying info vectors or not is not relevant. Once the loop slings around, the object is destroyed, and with it the std::string member variable ip. It may reside in the same memory space (the struct), but the reallocation of the string almost certainly will not. In other words, you're invoking undefined behavior.
A possible resolution to this is to use a smart pointer for the structure, passing its get() member to the thread, and pushing said-same smart pointer into your info vector ( retooled for smart pointers). I personally prefer a simpler approach, namely allocating both vectors before the threads are kicked off, thereby fixing their "innards" for by-address usage. From there you can send the structure address since the vector holds it for you:
// thread create
size_t tmp_num = 3;
m_thread.resize(tmp_num);
threads.resize(tmp_num);
for(size_t i = 0; i < tmp_num; i++)
{
m_thread[i].thread_id = i;
m_thread[i].ip = "127.0.0.1";
m_thread[i].port = 8001;
m_thread[i].timeout = 100;
rc = pthread_create(&threads[i], NULL, test_fun1, &m_thread[i]);
if (rc != 0)
return -1;
}
Regarding other issues, in your thread proc this doesn't compile:
char tmp_buf[1024] = '\0';
But that's pretty minor compared to the undefined behavior you're having.