1

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.

ameerosein
  • 523
  • 3
  • 16

5 Answers5

2

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.

nishantsingh
  • 4,537
  • 5
  • 25
  • 51
  • @ameerosein: Can you *guarantee* that the thread will end before `td[i]` goes out of scope? It's very easy to have this work when you step through in the debugger, or even when you are testing - but for the thing whose address you have passed to `multichaper` to disappear before the thread has a chance to read it when running on a heavily loaded production server. – Martin Bonner supports Monica Sep 21 '16 at 09:33
  • @user3286661 could you please check this question too ? http://stackoverflow.com/questions/39656285/how-to-multithreading-a-function-of-a-class-with-pthreads – ameerosein Sep 23 '16 at 08:39
  • @MartinBonner check my newer answer below and you can find how i guarantee that, thanks for noticing. – ameerosein Oct 06 '16 at 19:35
2

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:

  1. No casts

  2. Fewer explicit checks

  3. 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.

  4. No unintuitive void * returns (with the same lifetime problems).

Ami Tavory
  • 74,578
  • 11
  • 141
  • 185
  • could you please check this question too ? http://stackoverflow.com/questions/39656285/how-to-multithreading-a-function-of-a-class-with-pthreads?noredirect=1#comment66615110_39656285 – ameerosein Sep 23 '16 at 08:49
1

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!

0

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 (&params.mutex , NULL);
pthread_cond_init (&params.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), &params);
    pthread_cond_wait (&params.done, &params.mutex);
}
pthread_attr_destroy(&attr);
void* status;
for(int i=0; i < this->numberOfThread; i++ )
    rc = pthread_join(threads[i], &status);
pthread_mutex_destroy (&params.mutex);
pthread_cond_destroy (&params.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;
   ...
}
ameerosein
  • 523
  • 3
  • 16
-1

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 );
msc
  • 33,420
  • 29
  • 119
  • 214
  • 2
    Why do you think that is portable? Firstly there is no guarantee that `void *` is big enough to hold an `int`. Secondly, there is no guarantee that casting an int to `void *` won't change the bit pattern (I have used machines where I would expect it to do so - it would OR in the ring number.) – Martin Bonner supports Monica Sep 21 '16 at 07:51