Alberto Varandas
Alberto Varandas

Reputation: 23

Pthread_join returning variable value as 0

I want to insert pthread_join function on the following code to terminate my threads and get the variables value updated. After that my idea was to make a variable to add the new values I got from the threads and print it out. I have the following code, that seems to be working fine, but I want to update the variables a and b directly without any extra variable (I don't want to use aux_soma and aux_multiplicacao). If I try to update them directly, they get their value set to 0 (mostly variable a). Is there any way to do it the way I want? The code is written in portuguese, sorry about that, I hope you manage to understand it anyways.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <pthread.h>

void *soma(void *valor)
{
  int a = (intptr_t) valor;
  a = 10 + a;
  //printf("A thread soma terminou.\n");
  pthread_exit((void*)(intptr_t)a);
}

void *multiplicacao(void *valor)
{
  int a = (intptr_t) valor;
  a = 10 * a;
  //printf("A thread multiplicacao terminou.\n");
  pthread_exit((void *)(intptr_t)a);
}

int main()
{
  pthread_t p, t;

  int a = 5, b = 5;
  int aux_soma, aux_multiplicacao; // Variáveis auxiliares para evitar erros

  printf("\n\n"); // Duas linhas em branco; Para ficar separado e mais apresentável

  // Estava a dar erro no valor das variáveis e da soma, desta maneira não há erros
  int ra = pthread_create(&p, NULL, soma, (void *)(intptr_t)a);
  int rb = pthread_create(&t, NULL, multiplicacao, (void *)(intptr_t)b);
  pthread_join(t, (void **) &aux_multiplicacao);
  pthread_join(p, (void **) &aux_soma);

  a = aux_soma;
  b = aux_multiplicacao;

  int soma_ab = a + b;

  printf("\nIDthread soma = %d\n", (int) p);
  printf("IDthread multiplicacao = %d\n", (int) t);
  printf("a = %d\n", a);
  printf("b = %d\n", b);
  printf("Soma: a + b = %d\n", soma_ab);

  exit(0);
}

Thanks in advance.

Upvotes: 2

Views: 367

Answers (2)

R.. GitHub STOP HELPING ICE
R.. GitHub STOP HELPING ICE

Reputation: 215387

Most of what you're doing is fine in practice, and arguably optimal, relying on the ability to round-trip integer values through pointer types. This avoids the need to manage the lifetime of a pointed-to object, which can be a source of dangerous errors. However your program has serious UB that the compiler apparently told you about with a warning, and that you then tried to paper over with casts:

pthread_join(t, (void **) &aux_multiplicacao);
pthread_join(p, (void **) &aux_soma);

A cast to void ** is almost always wrong.

Here, you're telling pthread_join to store an object of type void * at &aux_multiplicacao (and then at &aux_soma), but the object at that address does not have the right type (or even size, in general) to store such an object. Instead you need:

void *tmp;
pthread_join(t, &tmp);
aux_multiplicacao = (intptr_t)tmp;
pthread_join(p, &tmp);
aux_soma = (intptr_t)tmp;

Upvotes: 0

user3386109
user3386109

Reputation: 34839

The code in the question is passing the value of a and b to the thread function, and then retrieving the result through pthread_join. A better solution is to pass the address of a and b to the thread functions. Then the functions can get the initial values of a and b. And the functions can update the values of a and b directly.

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

void *soma(void *valor)
{
    int *aptr = valor;
    int a = *aptr;    // get the initial value of 'a'

    a = 10 + a;       // do something with 'a'

    *aptr = a;        // set the final value of 'a'
    return NULL;
}

void *multiplicacao(void *valor)
{
    int *aptr = valor;
    int a = *aptr;    // get the initial value of 'a'

    a = 10 * a;       // do something with 'a'

    *aptr = a;        // set the final value of 'a'
    return NULL;
}

int main()
{
    int a = 5, b = 5;

    pthread_t p, t;
    int ra = pthread_create(&p, NULL, soma, &a);
    int rb = pthread_create(&t, NULL, multiplicacao, &b);
    if (ra != 0 || rb != 0)
        exit(1);
    pthread_join(t, NULL);
    pthread_join(p, NULL);

    int soma_ab = a + b;

    printf("a = %d\n", a);
    printf("b = %d\n", b);
    printf("Soma: a + b = %d\n", soma_ab);
}

Upvotes: 1

Related Questions