Resolução de equação de segundo grau utilizando threads?

,

Preciso criar um códgo que resolva equação de segundo grau utilizando threads. Procurando conteúdo sobre criação de threads me deparei com problema para passar as variáveis às funções threads.

Exemplo:

pthread_create(&t1, NULL, calcularX1, (void *)(&a, &b, *c)); 

Simplesmente não funciona. Alguém sabe como criar esse código? Eis o enunciado da lista:

Utilizando a linguagem C e o sistema operacional NU/Linux, desenvolva um programa que calcule as raízes, se existirem, de uma equação do segundo grau, sendo que as constantes envolvidas no cálculo deverão ser fornecidas pelo usuário via teclado. Para a resolução da equação, deve-se utilizar três processos além do processo
original. O primeiro processo será responsável por calcular o valor do delta e os demais deverão calcular as raízes da equação.

E o que você já fez?
Não sei se leu as regras do fórum, mas, não fazemos exercícios/trabalhos. Apenas ajudamos a esclarecer dúvidas específicas e pontuais a respeito de algo que você tenha construído.

Então, eu fiz um código mas tá terrível, eu realmente não sei como fazer isso.

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


float *calculateDelta(void a, void b, void c) 
{
	float *a1 = (float * )(a);
	float *b1 = (float * )(b);
	float *c1 = (float * )(c);
	
	return pow(b1, 2) - 4 * a1 * c1;
}

float *calculateX1(float a, float b, float delta) {
	float *a1 = (float * )(a);
	float *b1 = (float * )(b);
	float *c1 = (float * )(delta);
	return (-b1 + sqrt(c1)) / (2 * a1);
}

float *calculateX2(void *a, void *b, void *delta) {
	float *a1 = (float * )(a);
	float *b1 = (float * )(b);
	float *c1 = (float * )(delta);
	return (-b1 - sqrt(c1)) / (2 * a1);
}

int main()
{
  pthread_t x1,x2;
  float a = 0, b = 0, c = 0;

  printf("Digite o valor de A: ");
  scanf("%f", &a);

  printf("Digite o valor de B: ");
  scanf("%f", &b);

  printf("Digite o valor de C: ");
  scanf("%f", &c);

  float *delta = pthread_create(&t1, NULL, calculateDelta, (void * )(&a, &b, &c));

  if(delta > 0) {
    printf("Existem duas raizes reais distintas.\n");
  } else if(delta == 0){
    printf("Existem duas raizes reais iguais.\n");
  } else {
    printf("Delta: %f, não existem raizes reais.\n", delta);
    return 0;
  }

  float x1 = pthread_create(&t2, NULL, calculateX1, (void*)(a, b, delta));
  float x2 = pthread_create(&t1, NULL, calculateX2, (void *)(a, b, delta));

  printf("Delta: %f, X1: %f, X2: %f\n", delta, x1, x2);*/
  

  return 0;
}

Mas não funciona?

Não, aparecem infinitos erros. Li no Stachoverflow que parâmetros devem ser passados através de vetor. Testei:

for(i=0;i<3=i++) {
     phtread_create(&t1, NULL, calculateDelta, (void *)(valor[i]));
}

Mas gera outro problema, pois os valores passados não são o suficiente para a realização do cálculo.

Cara, precisa nada disso não, ao menos até onde eu lembro de C/C++;

Vamos lá:
Por que você passa os parâmetros para a função CalculateDelta como sendo void?

Eles não são float?

São, mas os tutoriais que eu li quanto a passagem de parâmetros mandam passar como void.

Cara, posta estes tutoriais pois eu quero me atualizar. Tudo o que aprendi em C/C++ foi por água abaixo agora.
Ainda mais quando vejo que, na função

Vocẽ usa como float.
Veja, o tipo void, até onde sei, só se usa em função, pois, ele determina que uma função não retornará nenhum valor. Como você quer calcular algo com tipo vazio?

A assinatura da função pthread_create é a seguinte:

 int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
                      void *(*start_routine) (void *), void *arg);

O último parâmetro é o que lhe interessa. Ele é o ponteiro que vai ser passado para a start_routine que você passa no terceiro parâmetro.

Existem algumas formas de passar valores “compostos” para sua rotina através desse ponteiro. A forma mais simples, no seu caso, é usar uma struct.

Faz o seguinte:

  1. Cria uma struct que carrega os 3 argumentos para sua função (a, b e c);
  2. Crie um objeto dessa struct e preencha os 3 valores com os parâmetros;
  3. Na chamada para pthread_create, passe a struct como void* (faça um cast explícito);
  4. Altere as assinaturas das funções calculateX1 e calculateX2 para receber apenas um parâmetro do tipo void*;
  5. Dentro dessas funções, você vai fazer outro cast explícito de void* para a sua struct com os parâmetros;
  6. Extraia os valores de a, b e c da struct e faça a conta que tiver que fazer.

A função pthread_create não retorna o valor da função que você passa por parâmetro para ela.

Por isso x1 e x2 não vão ter o valor retornado pelas funções.

Você precisa colocar um outro valor dentro da struct, chamado resultado (ou algo assim). É nesse valor que as funções vão escrever o resultado final do cálculo. O problema é que você não pode acessar esse valor assim que fizer as chamadas para pthread_create, pois existe uma condição de corrida onde a thread principal pode tentar acessar os resultados antes das funções terem os escrito nas structs. Você pode resolver essa condição com um semáforo.

Outra forma de capturar o retorno das threads é usando as funções pthread_exit e pthread_join.

É difícil explicar essas coisa num post curto. Para resolver esse exercício você precisa entender muito bem como funcionam ponteiros, casting e o tipo genérico void*.

Boa sorte.

Fiz um exemplo para te ajudar a começar. Entenda e extrapole pro seu caso.

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

struct arguments {
  int a, b;
};

void* sum (void* void_args) {
  struct arguments* args = (struct arguments *) void_args;
  float* result = malloc(sizeof(float));
  *result = args->a + args->b;
  return (void*) result;
}

int main () {
  struct arguments args;
  args.a = 1;
  args.b = 2;
  float* result;
  pthread_t t1;
  pthread_create(&t1, NULL, sum, &args);
  pthread_join(t1, (void**) &result);
  printf("Resultado: %.2f\n", *result);
  return 0;
}
2 curtidas