Прежде всего, цель pthread_join()
состоит в том, чтобы обновить void *
, заданный через его второй аргумент, чтобы получить результат функции потока (a void *
).
Когда вам нужно обновить int
как в scanf("%d", &my_var);
аргумент - это адрес обновляемого int
: int *
.
По тем же причинам вы обновляете void *
, предоставляя void **
.
В конкретной ситуации c вашего примера мы не используем возвращенный void *
обычным образом: это хитрость!
Поскольку указатель можно рассматривать как большое целое число Считая байты в очень длинной строке, уловка состоит в том, чтобы предположить, что этот указатель может просто хранить целочисленное значение, которое не относится ни к какой ячейке памяти.
В вашем примере возвращение (void *)42
эквивалентно говоря «вы найдете что-то интересное по адресу 42».
Но по этому адресу ничего не было размещено!
Это проблема? Нет, пока никто не пытается разыменовать этот указатель для извлечения чего-либо по адресу 42.
После выполнения pthread_join()
переменная res
обновлена и содержит возвращенные void *
: В данном случае 42.
Мы выполняем обратный трюк, предполагая, что информация, запомненная в этом указателе, не относится к ячейке памяти, а является простым целым числом.
Это работает, но это очень уродливо !
Основным преимуществом является то, что вы избегаете дорогостоящей стоимости mallo c () / free ()
void *myThread(void *arg)
{
int *result=malloc(sizeof(int));
*result=42;
return result;
}
...
int *res;
pthread_join(tid, &res);
int result=*res; // obtain 42
free(res);
Лучшим решением, чтобы избежать этой стоимости, было бы использование параметра потока функция.
void *myThread(void *arg)
{
int *result=arg;
*result=42;
return NULL;
}
...
int expected_result;
pthread_create(&tid, NULL, myThread, &expected_result);
pthread_join(tid, NULL);
// here expected_result has the value 42