4

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!

1

1 Answer 1

7

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.

Sign up to request clarification or add additional context in comments.

6 Comments

Oops can't believe I left that out >.< Thank you for the answer! I really appreciate it :)
@amura.cxg: Also note that you are creating an array of ints: so you should pass to malloc sizeof(int) * number_of_threads, not sizeof(int*) * number_of_threads
I tried the first implementation you suggested and when I try using return_vals[i] it gives me some large int (eg 134602832) when it should be 0 or -1. I do a memset on the array and set everything to 0 so the code does modify the value correctly but it doesn't put what I expect there. Is there something missing when trying to get the returned value out of the array?
@amura.cxg: That's why I put there that printf too so that it's clear how those values should be used. Both of those examples work fine for me, have a look at it again and try to find analogy with your code. In case you're stuck with it, then post it as a new question, maybe there's another error.
@LihO why in the first example inside foo you're casting an int to void *? are we supposed to return like this: return (void *) &i? Because void * is a pointer as far as I understand and i is not.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.