Параллельное и распределенное программирование на С++ - Хьюз Камерон
Шрифт:
Интервал:
Закладка:
Для завершения вызывающего потока используется функция pthread_exit () Значение value_ptr передается потоку, который вызывает функцию pthread_join() для этого потока. Еще не выполненные процедуры, связанные с «уборкой», будут выполнены вместе с деструкторами, предусмотренными для потоковых данных. Никакие ресурсы, используемые потоками, при этом не освобождаются.
Синопсис
#include <pthread.h>
int pthread_exit(void *value_ptr);
При завершении последнего потока в процессе завершается сам процесс со статусом завершения, равным 0. Эта функция не может вернуться к вызывающему потоку и не определяет никаких кодов ошибок.
Для отмены выполнения некоторого потока по инициативе потока из того же адресного пространства используется функция pthread__cancel (). Отменяемый поток задается параметром thread.
Синопсис
#include <pthread.h>
int pthread_cancel(pthread_t thread);
Обращение к функции pthread_cancel () представляет собой запрос аннулировать поток. Этот запрос может быть удовлетворен немедленно, с отсрочкой или проигнорирован. Когда произойдет аннулирование (и произойдет ли оно вообще), зависит от типа аннулирования и состояния потока, подлежащего этой кардинальной операции. Для удовлетворения запроса на отмену потока предусмотрен процесс аннулирования, который происходит асинхронно (т.е. не совпадает по времени) по отношению к выходу из функции pthread_cancel() и ее возврату в вызывающий поток. Если потоку нужно выполнить «уборочные» задачи, они обязательно выполняются. После выполнения последней такой задачи-обработчика вызываются деструкторы потоковых объектов, если таковые предусмотрены, и только после этого поток завершается. В этом и состоит процесс аннулирования потока. При успешном выполнении функция pthread_cancel () возвращает число 0 , в противном случае — код ошибки. Эта функция не выполнится успешно, если параметр thread не соответствует ни одному из существующих потоков.
Некоторые потоки могут потребовать принять меры безопасности против преждевременного их аннулирования. Внесение в потоковую функцию средств безопасности может предотвратить возникновение некоторых нежелательных ситуаций. Потоки разделяют общие данные, и (в зависимости от используемой потоковой модели) один поток может обрабатывать данные, которые должны быть переданы другому потоку для последующей обработки. Пока поток обрабатывает данные, он является их единственным обладателем благодаря блокированию мьютекса, связанного с этими данными. Если поток, имеющий заблокированный мьютекс, аннулируется до его освобождения, возникает взаимоблокировка. Для того чтобы снова использовать данные, их следует привести в определенное состояние. Если поток отменяется до освобождения мьютекса, могут возникнуть нежелательные условия. Другими словами, в зависимости от типа обработки, которую выполняет поток, его аннулирование должно происходить тогда, когда это безопасно. Об опасных и безопасных периодах «знает» только сам поток, и поэтому только он может предотвратить свое аннулирование в опасные периоды. Следовательно, круг потоков, которые можно аннулировать, должен быть ограничен потоками, которые не относятся к числу «жизненно важных» или которые не имеют блокировок ресурсов. Кроме того, аннулирование может быть отсрочено до тех пор, пока не будут выполнены «жизненно важные» действия.
Состояние готовности к аннулированию (cancelability state) описывает условия, при которых поток может (или не может) быть аннулирован. Тип аннулирования (cancelabilty type) потока определяет способность потока продолжать выполнение после получения запросов на аннулирование. Поток может отреагировать на аннулирующий запрос немедленно или отложить аннулирование до определенной (более поздней) точки в его выполнении. Состояние готовности к аннулированию и тип аннулирования устанавливаются динамически самим потоком.
Для определения состояния готовности к аннулированию и типа аннулирования вызывающего потока используются функции p thread_setcancelstate() pthread_setcanceltype(). Функция pthread_setcancelstate() устанавливает вызывающий поток в состояние, заданное параметром state, и возвращает предыдущее состояние в параметре oldstate.
Синопсис
#include <pthread.h>
int pthread_setcancelstate(int state, int *oldstate);
int pthread_setcanceltype(int type, int *oldtype);
Параметры state и oldstate могут принимать такие значения:
PTHREAD_CANCEL_DISABLE
PTHREAD_CANCEL_ENABLE
Значение PTHREAD_CANCEL_DISABLE определяет состояние, в котором поток будет игнорировать запрос на аннулирование, а значение PTHREAD_CANCEL_ENABLE - состояние, в котором поток «согласится» выполнить соответствующий запрос (это состояние по умолчанию устанавливается для каждого нового потока). При успешном выполнении функция возвращает число 0 , в противном случае — код ошибки. Функция pthread_setcancelstate() не может выполниться успешно, если переданное
значение параметра state окажется недействительным. Функция pthread_setcanceltype () устанавливает для вызывающего потока тип аннулирования, заданный параметром type, и возвращает предыдущее значение типа в параметре oldtype. Параметры type и oldtype могут принимать такие значения:
PTHREAD_CANCEL_DEFFERED
PTHREAD_ASYNCHRONOUS
Значение PTHREAD_CANCEL_DEFFERED определяет тип аннулирования, при котором поток откладывает завершение до тех пор, пока он не достигнет точки, в котором его аннулирование возможно (этот тип по умолчанию устанавливается для каждого нового потока). Значение PTHREAD_CANCEL_ASYNCHRONOUS определяет тип аннулирования, при котором поток завершается немедленно. При успешном выполнении функция возвращает число 0 , в противном случае— код ошибки. Функция pthread_setcanceltype() не может выполниться успешно, если переданное ей значение параметра type окажется недействительным.
Функции pthread_setcancelstate() и pthread_setcanceltype() используются вместе для установки отношения вызывающего потока к потенциальному запросу на аннулирование. Возможные комбинации значений состояния и типа аннулирования перечислены и описаны в табл. 4 .5.
Таблица 4.5. Комбинации значений состояния и типа аннулирования
Состояние Тип Описание
PTHREAD_CANCEL_ENABLE (PTHREAD_CANCEL_DEFERRED) Отсроченное аннулирование. Эти состояние и тип аннулирования потока устанавливаются по умолчанию. Аннулирование потока происходит, когда он достигает соответствующей точки в своем выполнении или когда программист определяет точку аннулирования с помощью функции pthread_testcancel()
PTHREAD_CANCEL_ENABLE (PTHREAD_CANCEL_ASYNCHRONOUS)
Асинхронное аннулирование. Аннулирование потока происходит немедленно
PTHREAD_CANCEL_DISABLE (любое)
Аннулирование запрещено. Оно вообще не выполняется
Точки аннулирования потоков
Если удовлетворение запроса на аннулирование потока откладывается, значит, оно произойдет позже, когда это делать «безопасно», т.е. когда оно не попадает на период выполнения некоторого критического кода, блокирования мьютекса или пребывания данных в некотором «промежуточном» состоянии. Вне этих «опасных» разделов кода потоков вполне можно устанавливать точки аннулирования. Точка аннулирования — это контрольная точка, в которой поток проверяет факт существования каких-либо ждущих (отложенных) запросов на аннулирование и, если таковые имеются, разрешает завершение.
Точки аннулирования можно пометить с помощью функции pthread_testcancel () • Эта функция проверяет наличие необработанных запросов на аннулирование. Если они есть, она активизирует процесс аннулирования в точке своего вызова. В противном случае функция продолжает выполнение потока без каких-либо последствий. Вызов этой функции можно разместить в любом месте кода потока, которое считается безопасным для его завершения.