user5561927
user5561927

Reputation:

Why the value returned by a pthread is not same as passed to the thread function?

What I understand pthread_join manual is my program should output the same value I supplied to print_xs but the output obtained is:

Message from printxs 11131 a
Message from printxs 11234 b
32766 -16
32766 0

The Program:

#include<stdio.h>
#include<pthread.h>

typedef struct paramsThread{
        char c;
        int count;
} threadPara;

void* print_xs(void* unused){
        threadPara *tp = (threadPara *)unused;
        int i=tp->count;

        printf("Message from printxs %d %c\n", tp->count, tp->c);
        return (void*)tp;
}

int main(){
        pthread_t thread1, thread2;
        threadPara t1,t2,t3,t4;
        t1.c = 'a';
        t2.c = 'b';
        t1.count = 11131;
        t2.count = 11234;
        t3.count=0;
        pthread_create(&thread1, NULL, &print_xs, &t1);
        pthread_create(&thread2, NULL, &print_xs, &t2);
        pthread_join(thread1,(void*)&t3);
        printf("%d %d\n", t3.count, t3.c);
        pthread_join(thread2,(void*)&t4);
        printf("%d %d\n", t4.count, t4.c);
        return 0;
}

Can some one explain why this is happening?

Upvotes: 1

Views: 104

Answers (2)

alk
alk

Reputation: 70893

The thread function returns an address, a void*.

pthread_join() receives this address to where its 2nd parameter (a void**) points to.

So to make use of this in your code instead of

        pthread_join(thread1, (void*)&t3);

do

        {
          void * pv;
          pthread_join(thread1, &pv);
          if (NULL != pv)
          {
            t3 = *((threadPara*) pv);
          }
        }

As a side note: In C there is no need to cast to/from void-pointers from/to other pointers, the pointers involved get converted implicitly.

So this code

void* print_xs(void* unused){
    threadPara *tp = (threadPara *)unused;
    int i=tp->count;

    printf("Message from printxs %d %c\n", tp->count, tp->c);
    return (void*)tp;
}

may very well be written like this:

void* print_xs(void* unused){
    threadPara *tp = unused;
    int i=tp->count;

    printf("Message from printxs %d %c\n", tp->count, tp->c);
    return tp;
}

Upvotes: 0

Some programmer dude
Some programmer dude

Reputation: 409166

If you read a pthread_join reference or manual page you will see that the second argument is a pointer to a pointer. This is a way to emulate pass by reference in C.

The pointer the thread function returns is copied into another pointer.

The solution is to use pointers for t3 and t4 instead:

threadPara t1, t2;
threadPara *t3, *t4;

// ...

pthread_join(thread1,(void**)&t3);  // Pass pointer to the pointer, emulating pass by reference
printf("%d %d\n", t3->count, t3->c);
pthread_join(thread2,(void**)&t4);
printf("%d %d\n", t4->count, t4->c);

If you print the pointers, or use a debugger, then you will see that t3 will be pointing to t1 (i.e. t3 == &t1) and the same for t4 and t2.

Upvotes: 5

Related Questions