Параллельное и распределенное программирование на С++
Шрифт:
значение параметра state окажется недействительным. Функция pthread_setcanceltype устанавливает для вызывающего потока тип аннулирования, заданный параметром type, и возвращает предыдущее значение типа в параметре oldtype. Параметры type и oldtype могут принимать такие значения:
PTHREAD_CANCEL_DEFFERED
PTHREAD_ASYNCHRONOUS
Значение PTHREAD_CANCEL_DEFFERED определяет тип аннулирования, при котором поток откладывает завершение до тех пор, пока он не достигнет точки, в котором его аннулирование возможно (этот тип по умолчанию устанавливается для каждого нового потока). Значение PTHREAD_CANCEL_ASYNCHRONOUS определяет тип аннулирования, при котором поток завершается
Функции 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 • Эта функция проверяет наличие необработанных запросов на аннулирование. Если они есть, она активизирует процесс аннулирования в точке своего вызова. В противном случае функция продолжает выполнение потока без каких-либо последствий. Вызов этой функции можно разместить в любом месте кода потока, которое считается безопасным для его завершения.
Синопсис
#include <pthread.h>
void pthread_testcancel(void)
Программа 4.3 содержит функции, которые вызывают функции pthread_setcancelstate, pthread_setcanceltype и pthread_testcancel, связанные с установкой типа аннулирования потока и состояния готовности к аннулированию.
#include <iostream>
#include <pthread.h>
void *task1(void *X)
{
int OldState;
// disable cancelability
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,&OldState);
for(int Count = 1;Count < 100;Count++)
{
cout << «thread A is working: " << Count << endl;
}
}
void *task2(void *X)
{
int OldState,OldType;
// enable cancelability, asynchronous
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,&OldState);
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,&OldType);
for(int Count = 1;Count < 100;Count++)
{
cout <<
}
}
void *task3(void *X)
{
int OldState,OldType;
// enable cancelability, deferred
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,&OldState);
pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED,&OldType);
for(int Count = 1;Count < 1000;Count++)
{
cout << «thread C is working: " << Count << endl;
if((Count%100) == 0){
pthread_testcancel;
}
}
}
В программе 4.3 каждая задача устанавливает свое условие аннулирования. В задаче task1 аннулирование потока запрещено, поскольку вся она состоит из критического кода, который должен быть выполнен до конца. В задаче task2 аннулирование потока разрешено. Обращение к функции pthread_setcancelstate является необязательным, поскольку все новые потоки имеют статус разрешения аннулирования. Тип аннулирования здесь устанавливается равным значению PTHREAD_CANCEL_ASYNCHRONOUS Это означает, что после поступления запроса на аннулирование поток немедленно запустит соответствующую процедуру, независимо от того, на какой этап его выполнения придется этот запрос. А поскольку этот поток установил для себя именно такой тип аннулирования, значит, он не выполняет никакого «жизненно важного» кода. Например, вызовы системных функций должны попадать под категорию опасных для аннулирования, но в задаче task2 таких нет. Там выполняется лишь цикл, который будет работать до тех пор, пока не поступит запрос на аннулирование. В задаче task3 аннулирование потока также разрешено, а тип аннулирования устанавливается равным значению PTHREAD_CANCEL_DEFFERED. Эти состояние и тип аннулирования действуют по умолчанию для новых потоков, следовательно, обращения к функциям pthread_setcancelstate и pthread_setcanceltype здесь необязательны. Критический код этого потока здесь может спокойно выполняться после установки состояния и типа аннулирования, поскольку процедура завершения не стартует до вызова функции pthread_testcancel . Если не будут обнаружены ждущие запросы, поток продолжит свое выполнение до тех пор, пока не встретит очередные обращения к функции pthread_testcancel (если таковые предусмотрены). В задаче task3 функция pthread_cancel вызывается только после того, как переменная Count без остатка разделится на число 100 . Код, расположенный между точками аннулирования потока, не должен быть критическим, поскольку он может не выполниться.
Программа 4.4 содержит управляющий поток, который делает запрос на аннулирование каждого рабочего потока.
// Программа 4.4
int main(int argc, char *argv[]) {
pthread_t Threads[3]; void *Status;
pthread_create(&(Threads[0]),NULL,taskl, NULL); pthread_create(&(Threads[l]), NULL,task2,NULL); pthread_create(&(Threads[2]),NULL,task3,NULL);
pthread_cancel(Threads[0]); pthread_cancel(Threads[l]); pthread_cancel(Threads[2]);
for(int Count = 0;Count < 3;Count++) {