Чтобы задать статус отсоединения потока, воспользуйтесь функцией pthread_attr_setdetachstate(). Первый ее аргумент — это указатель на объект атрибутов потока, второй — требуемый статус. Ожидаемые потоки создаются по умолчанию, поэтому в качестве второго аргумента имеет смысл указывать только значение PTHREAD_CREATE_DETACHED.
Программа, представленная в листинге 4.5, создает отсоединенный поток, устанавливая соответствующим образом атрибуты потока.
#include <pthread.h>
void* thread_function(void* thread_arg) {
/* Тело потоковой функции... */
}
int main() {
pthread_attr_t attr;
pthread_t thread;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
pthread_create(&thread, &attr, &thread_function, NULL);
pthread_attr_destroy(&attr);
/* Тело основной программы... */
/* Дожидаться завершения второго потока нет необходимости. */
return 0;
}
Даже если поток был создан ожидаемым, его позднее можно сделать отсоединенным. Для этого нужно вызвать функцию pthread_detach(). Обратное преобразование невозможно.
4.2. Отмена потока
Обычно поток завершается при выходе из потоковой функции или вследствие вызова функции pthread_exit(). Но существует возможность запросить из одного потока уничтожение другого. Это называется отменой, или принудительным завершением, потока.
Чтобы отменить поток, вызовите функцию pthread_cancel(), передав ей идентификатор требуемого потока. Далее можно дождаться завершения потока. Вообще-то, это обязательно нужно делать с целью освобождения ресурсов, если только поток не является отсоединенным. Отмененный поток возвращает специальное значение PTHREAD_CANCELED.
Во многих случаях поток выполняет код, который нельзя просто взять и прервать. Например, поток может выделить какие-то ресурсы, поработать с ними, а затем удалить. Если отмена потока произойдет где-то посередине, освободить занятые ресурсы станет невозможно, вследствие чего они окажутся потерянными для системы. Чтобы учесть эту ситуацию, поток должен решить, где и когда он может быть отменен.
С точки зрения возможности отмены поток находится в одном из трех состояний.
■ Асинхронно отменяемый. Такой поток можно отменить в любой точке его выполнения.
■ Синхронно отменяемый. Поток можно отменить, но не везде. Запрос на отмену помещается в очередь, и поток отменяется только по достижении определенной точки.
■ Неотменяемый. Попытки отменить поток игнорируются. Первоначально поток является синхронно отменяемым.
4.2.1. Синхронные и асинхронные потоки
Асинхронно отменяемый поток "свободен" в любое время. Синхронно отменяемый поток, наоборот, бывает "свободным", только когда ему "удобно". Соответствующие места в программе называются точками отмены. Запрос на отмену помещается в очередь и находится в ней до тех пор, пока поток не достигнет следующей точки отмены.
Чтобы сделать поток асинхронно отменяемым, воспользуйтесь функцией pthread_setcanceltype(). Эта функция влияет на тот поток, в котором она была вызвана. Первый ее аргумент должен быть PTHREAP_CANCEL_ASYNCHRONOUS в случае асинхронных потоков и PTHREAD_CANCEL_DEFERRED — в случае синхронных потоков. Второй аргумент — это указатель на переменную, в которую записывается предыдущее состояние потока.
Вот как можно сделать поток асинхронным:
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
Что такое точка отмены и где она должна находиться? На этот вопрос нельзя дать прямой ответ. Точка отмены создается с помощью функции pthread_testcancel(). Все, что она делает, — это обрабатывает отложенный запрос на отмену в синхронном потоке. Ее следует периодически вызывать в потоковой функции в ходе длительных вычислений, там, где поток можно завершить без риска потери ресурсов или других побочных эффектов.