Подтвердить что ты не робот

Есть ли недопустимый идентификатор pthread_t?

Я бы назвал pthread_join для данного идентификатора потока, но только если этот поток был запущен. Безопасное решение может заключаться в том, чтобы добавить переменную, чтобы отслеживать, какой поток был запущен или нет. Однако мне интересно, возможно ли проверять переменные pthread_t, что-то вроде следующего кода.

pthread_t thr1 = some_invalid_value; //0 ?
pthread_t thr2 = some_invalid_value;

/* thread 1 and 2 are strated or not depending on various condition */
....

/* cleanup */
if(thr1 != some_invalid_value)
    pthread_join(&thr1);

if(thr2 != some_invalid_value)
    pthread_join(&thr2);

Где some_invalid_value может быть 0 или макрос PTHREAD_INVALID_ID, зависящий от реализации

PS: Мое предположение заключается в том, что типы pthread_t сопоставимы и присваиваются, предположение основано на

PPS: Я хотел сделать это, потому что я думал, что вызов pthread_join на недопустимом идентификаторе потока был undefinde. Это не. Тем не менее, соединение ранее связанного потока IS undefined. Теперь предположим, что вышеуказанная "функция" вызывается многократно. Необычно вызов pthread_join и проверка результата могут привести к вызову pthread_join в ранее соединенном потоке.

4b9b3361

Ответ 1

Ваше предположение неверно для начала. Объекты pthread_t непрозрачны. Вы не можете сравнивать типы pthread_t непосредственно в C. Вместо этого вы должны использовать pthread_equal.

Другое соображение состоит в том, что если pthread_create терпит неудачу, содержимое вашего pthread_t будет undefined. Он больше не может быть установлен на ваше недопустимое значение.

Предпочитаю сохранить возвращаемые значения вызовов pthread_create (вместе с идентификаторами потоков) и использовать их для определения правильности запуска каждого потока.

Ответ 2

Как было предложено Тони, вы можете использовать pthread_self() в этой ситуации.

Но не сравните thread_t с помощью == или !=. Используйте pthread_equal.

На странице pthread_self:

Следовательно, переменные типа pthread_t не могут сравниваться по размеру с использованием оператора равенства C (==); Вместо этого используйте pthread_equal (3).

Ответ 3

К сожалению, в системах, где pthread_t является указателем, pthread_equal() может возвращать равенство, даже если два аргумента относятся к различным потокам, например. поток может выйти, и новый поток может быть создан с тем же значением указателя pthread_t.

Ответ 4

Недавно я столкнулся с этой проблемой. Если pthread_create() не удалось, я закончил с undefined, недопустимым значением, хранящимся в моей структуре phtread_t. В результате я сохраняю логическое значение, связанное с каждым потоком, который получает значение true, если pthread_create() преуспел.

Тогда все, что мне нужно сделать, это:

void* status;
if (my_thread_running) {
  pthread_join(thread, &status);
  my_thread_running = false;
}

Ответ 5

Это отличный вопрос, который я действительно хотел бы получить больше обсуждений в классах C++ и тестах кода.

Один вариант для некоторых systems--, который может показаться вам излишним, но пригодившимся для me--, состоит в том, чтобы запустить поток, который не делает ничего, кроме эффективного ожидания сигнала разрыва, а затем завершается. Этот поток продолжает работать в течение всего жизненного цикла приложения, выходя из строя очень поздно в последовательности завершения работы. До этого момента идентификатор этого потока можно эффективно использовать как "недопустимый поток" value-- или, что более вероятно, как "неинициализированный" sentinel-- для большинства целей. Например, мои библиотеки отладки обычно отслеживают потоки, из которых были заблокированы мьютексы. Это требует инициализации этого значения отслеживания для чего-то разумного. Поскольку POSIX довольно глупо отказывается требовать, чтобы платформы определяли INVALID_THREAD_ID, и потому что мои библиотеки позволяют main() блокировать вещи (делая проверки pthread_self, которые являются хорошим решением, pthread_create непригодными для отслеживания блокировок), это решение, которое я пришел использовать, Работает на любой платформе.

Однако обратите внимание, что вам нужно немного больше поработать над дизайном, если вы хотите, чтобы он мог инициализировать статические ссылки на потоки на недопустимые значения.

Ответ 6

Я портировал некоторый код, который использовал pthreads, в приложение C++, и у меня был тот же вопрос. Я решил, что проще было переключиться на объект C++ std::thread, который имеет метод .joinable() чтобы решить, присоединяться или нет, т.е.

 if (t.joinable()) t.join();

Я обнаружил, что простой вызов pthead_join значения pthread_t (в результате сбоя pthread_create) вызвал ошибку сегмента, а не просто возвращаемое значение ошибки.