Возврат результата из потока через pthread_join(): не могу вернуть результат
Я учусь работать с потоками в C.
Фактически, при этом вызывается две функции: pthread_create() и pthread_join(). И происходит вызов кода, который описан в так называемой "поточной функции". Пример я приведу чуть ниже.
С передачей аргументов внутрь функциии - нет проблем, я создаю структуру, всё туда кладу, преобразовываю струтуру к (void *), а внутри поточной функции выполняю обратное преобразование.
А вот вернуть результат из поточной функции - не получается.
Я убил на это море времени.
Я прочиал все ссылки по запросу "c pthread_join return value example" и посмотрел видео с утьюба.
Понятнее не стало. Моя проблема, как я её вижу, вот в чем:
У меня в pthread_join() возвращается адрес, по которому лежит результат.
Но этот адрес - это указатель типа void *. И я не могу этот адрес преобразовать обартно к типу, который я ожидаю вернуть из функции. То есть, я не могу void * преобразовывать к произвольному типу: меня компилятор бъет по рукам.
Нет ли какого то способа, достаточно общего, чтобы я мог вернуть из "поточной функции" не только int (это единственный пример, который работает), но и другой тип? Идеально было бы тоже возвращать структуру, в котрую я могу положить уже что угодно.
Второй способ, который мне приходит в голову - это возвращать результат через ту же структуру, которая передаётся в качестве аргумента (то есть, предусмотреть в ней поля для возврата результата). Но, прежде чем идти этим путём, я бы хотел получить от Вас совет.
Спасибо заранее!
Теперь - код, в котором первый пример работает, а второй (который отличается тем, что я "механически" поменял тип int на тип float - уже не работает)
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
struct thread_args{
int x;int y;
};
void* func_int_from_thread(void *arg){
struct thread_args *par;
par = (struct thread_args*) arg;
int* res = malloc(sizeof(int));
*res = 150;
return (void*)res;
};
void* func_float_from_thread(void *arg){
struct thread_args *par;
par = (struct thread_args*) arg;
float* res = malloc(sizeof(float));
*res = 147.4;
return (void*)res;
};
int main(){
struct thread_args targs = { .x=10, .y=25 };
// Шаг 0 - возвращаем целое число
int* res_int; // это указатель на целое число. То есть указатель на то место в памяти, где будет лежать результат
pthread_t pid0;
pthread_create ( &pid0, NULL, func_int_from_thread, (void*)&targs );
pthread_join ( pid0, (void**)&res_int );
int tmp = *res_int;
printf ( "Integer result: %d \n", tmp );
// результат возвращается нормально. Отметим следующие особеннсти:
// 1) выделение памяти происходит внутри "поточной функции" func_int_from_thread
// 2) возвращается из "поточной функции" всегда указатель
// Шаг 1 - возвращаем float
// Напишем вторую "поточную функцию", которая возвращает float
float* res_float; // это указатель на float - число. То есть указатель на то место в памяти, где будет лежать результат
pthread_t pid1;
pthread_create ( &pid1, NULL, func_float_from_thread, (void*)&targs );
pthread_join ( pid1, (void**)&res_float );
float tmp2 = *res_float;
printf ( "Float result: %d \n", tmp2 );
}
Ответы (1 шт):
Большое спасибо всем за подсказки.
В общем, моей первоначальной целью было - научиться возвращать массивы из pthread_join().
Массивы я так и не научился возвращать: всегда наталкивался на segmantation fault.
Я не смог сделать этого иначе, чем "обернув" массив в структуру.
Когда есть структура - то она как то "изолирует" меня от этого бесконечноко кол-ва "звездочек", которые надо дописать, чтобы преобразовать тип "туда и обратно".
У меня получился такой вот работающий пример. Надеюсь, он еще кому нибудь поможет.
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
struct thread_args{
int x;int y;
float f;
};
struct thread_rez{
float rez;
int* arr;
};
void* func_int_from_thread(void *arg){
struct thread_args *par;
par = (struct thread_args*) arg;
int* res = malloc(sizeof(int));
*res = 150;
return (void*)res;
};
void* func_float_from_thread(void *arg){
struct thread_args *par;
par = (struct thread_args*) arg;
float* res = malloc(sizeof(float));
*res = 147.4;
return (void*)res;
};
void* func_struct_from_thread(void *arg){
struct thread_args *par;
par = (struct thread_args*) arg;
struct thread_rez* trez = malloc(sizeof(trez));
trez->arr = malloc(sizeof(int) * 3);
trez->rez=120.2;
trez->arr[0] = 1; trez->arr[1] = 2; trez->arr[2] = 3;
return (void*)trez;
};
int main(){
struct thread_args targs = { .x=10, .y=25 };
// Шаг 0 - возвращаем целое число
int* res_int; // это указатель на целое число. То есть указатель на то место в памяти, где будет лежать результат
pthread_t pid0;
pthread_create ( &pid0, NULL, func_int_from_thread, (void*)&targs );
pthread_join ( pid0, (void**)&res_int );
int tmp = *res_int;
printf ( "Integer result: %d \n", tmp );
// результат возвращается нормально. Отметим следующие особеннсти:
// 1) выделение памяти происходит внутри "поточной функции" func_int_from_thread
// 2) возвращается из "поточной функции" всегда указатель
// Шаг 1 - возвращаем float
// Напишем вторую "поточную функцию", которая возвращает float
float* res_float; // это указатель на float - число. То есть указатель на то место в памяти, где будет лежать результат
pthread_t pid1;
pthread_create ( &pid1, NULL, func_float_from_thread, (void*)&targs );
pthread_join ( pid1, (void**)&res_float );
float tmpf = *res_float;
printf ( "Float result: %f \n", tmpf );
// Шаг 2 - возвращаем структуру
struct thread_rez* sres;
pthread_t pid2;
pthread_create ( &pid2, NULL, func_struct_from_thread, (void*)&targs );
pthread_join ( pid2, (void**)& sres);
printf ( "Struct result 1: %f \n", sres->rez );
printf ( "Struct result 2: \n");
for(int i=0; i<3; ++i)
printf("%d ", sres->arr[i]);
}
Вывод программы:
Integer result: 150
Float result: 147.399994
Struct result 1: 120.199997
Struct result 2:
1 2 3