Это типичное определение PTHREAD_CANCELED
(дословно цитируется /usr/include/pthread.h
на компьютере, на котором я это печатаю, на котором работает Linux с GNU libc):
#define PTHREAD_CANCELED ((void *) -1)
Так что, если у вас есть такой код для проверки отмены:
void *thread_result;
int rv = pthread_join(child, &thread_result);
if (rv)
error_exit("pthread_join failed", rv);
if (thread_result == PTHREAD_CANCELED)
error_exit("thread canceled", 0);
у вас не должно быть процедуры потока, подобной этой:
static void *appears_to_be_canceled(void *unused)
{
return ((void *) -1);
}
потому что PTHREAD_CANCELED
и ((void *) -1)
равны. Обратите внимание, что число не обязательно должно быть минус 1, оно может отличаться от системы к системе, и нет хорошего способа узнать, что это за время компиляции, потому что ((void *)...)
не может использоваться в выражении #if
.
Есть два хороших способа избежать этой проблемы:
- Не используйте отмену потока, поэтому вам не нужно проверять
PTHREAD_CANCELED
и не беспокоиться о его числовом значении. Это хорошая идея по ряду других причин, наиболее важно то, что отмена делает написание надежного многопоточного кода еще сложнее, чем это уже есть.
Возвращать только правильные указатели из ваших потоковых процедур, а не числа. Хорошая идиома для подражания выглядит так:
struct worker_data
{
// put _everything_ your thread needs to access in here
};
static void *worker_proc (void *data_)
{
struct worker_data *data = data_;
// do stuff with `data` here
return data_;
}
Возвращение объекта worker_data
означает, что коду, вызывающему pthread_join
, не нужно отслеживать, какой объект worker_data
соответствует какому pthread_t
. И это также означает, что возвращаемое значение успешно завершенного потока гарантированно не будет равно PTHREAD_CANCELED
, потому что PTHREAD_CANCELED
гарантированно не будет сравниваться ни с одним допустимым указателем.