Search code examples
cpthreadspthread-join

pthread Return Values to an Array


I am currently working on a project that uses pthreads. The project so far starts a user specified number of threads and does some work on each thread then closes. Each thread is stored in a dynamically allocated array of memory. I do this using:

threads = malloc(number_of_threads * sizeof(pthread_t));

Then I create each thread in a for-loop:

pthread_create(&(threads[i]), NULL, client_pipe_run, (void *) &param[i]);

What I need to do next is store the return values of these threads. My understanding is that I need to pass pthread_join the address of a pointer I want to have the return value stored in. This is where I get a little confused. I'm fine with pointers up to this point then my brain kind of has a melt down haha. This is my idea on how to acheive this but I'm not confident that this is correct:

int *return_vals = malloc(sizeof(int) * number_of_threads);
for(i = 0; i< number_of_threads; i++)
{
pthread_join(&(threads[i]),(void *) &(return_vals[i]));
}

Then to get the return value I would do something similar to:

int val = *(return_val[0]);

Any help on the this would be greatly appreciated!


Solution

  • Note that you are allocating memory for your threads like this:

    threads = malloc(number_of_thread * sizeof(pthread_t));
    

    but for return values you do:

    int *return_vals = malloc(sizeof(int *));
    

    i.e. number of threads should be taken in count here too:

    int *return_vals = malloc(number_of_thread * sizeof(int));
    

    Then you can either cast the return value to void*:

    void *foo(void *arg) {
        int i = 7;
        return (void*)i;
    }
    
    int main(void) {
        int i = 0;
        int thread_count = 3;
        pthread_t* threads = malloc(thread_count * sizeof(pthread_t));
        int *return_vals = malloc(thread_count * sizeof(int));
    
        // create threads:
        for(i = 0; i < thread_count; ++i)
            pthread_create(&threads[i], NULL, &foo, NULL);
    
        // wait untill they finish their work:
        for(i = 0; i < thread_count; ++i)
            pthread_join(threads[i], (void**) &return_vals[i]);
    
        // print results:
        for(i = 0; i < thread_count; ++i)
            printf("Thread %d returned: %d\n", i, return_vals[i]);
    
        // clean up:
        free(return_vals);
        free(threads);
    
        return 0;
    }
    

    or you can make sure that your code doesn't make any presumptions about size of the type you're returning being less or equal to sizeof(void*) and allocate the memory for the return value dynamically within the thread:

    void *foo(void *arg) {
        int* ret = malloc(sizeof(int));
        *ret = 7;
        return ret;
    }
    
    int main(void) {
        int i = 0;
        int thread_count = 3;
        pthread_t* threads = malloc(thread_count * sizeof(pthread_t));
    
        // array of pointers to return values of type int:
        int **return_vals = calloc(thread_count, sizeof(int*));
    
        // create threads:
        for(i = 0; i < thread_count; ++i)
            pthread_create(&threads[i], NULL, &foo, NULL);
    
        // wait untill they finish their work:
        for(i = 0; i < thread_count; ++i)
            pthread_join(threads[i], (void**) &return_vals[i]);
    
        // print results:
        for(i = 0; i < thread_count; ++i)
            printf("Thread %d returned: %d\n", i, *return_vals[i]);
    
        // clean up:
        for(i = 0; i < thread_count; ++i)
            free(return_vals[i]);
        free(return_vals);
        free(threads);
    
        return 0;
    }
    

    But in case you chose the latter one, be careful about possible memory leaks you might end up with.