Обе рассмотренные функции установок [23]параметров отмены при успешном выполнении возвращают значение EOK.
Итак, действия потока на запрос его завершения будут определяться текущей комбинацией двух установленных для него параметров: состоянием и типом отмены.
Теперь о том, чем же отличается отмена асинхронно и синхронно завершаемых потоков. Поток с асинхронным типом отмены (установленный с
PTHREAD_CANCEL_ASYNCHRONOUSPTHREAD_CANCEL_DEFERREDpthread_cancel()
void pthread_testcancel(void);Каждый вызов
pthread_testcancel()pthread_testcancel()PTHREAD_CANCEL_DISABLEpthread_testcancel()( Очень важно!) Достаточно много библиотечных функций могут сами устанавливать точки отмены. Более того, такие функции могут косвенно вызываться из других функций в программе и тем самым неявно устанавливать точки отмены. Информацию о таких функциях следует искать в справочной man-странице по функции
pthread_testcancel()pthread_testcancel()Если состояние отмены потока, как это описывалось ранее, установлено в
PTHREAD_CANCEL_DISABLEПокажем, как могут быть использованы все эти предосторожности в коде функции потока, чтобы сделать код безопасным с позиции возможной асинхронной отмены потока извне:
void* function(void* data) {
int state;
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &state);
// ... здесь выполняется инициализация ...
pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
pthread_setcancelstate(&state, NULL);
while (true) {
struct blockdata *blk = new blockdata;
// ... обработка блока данных blk ...
delete blk;
pthread_testcancel();
}
}
...
pthread_t tid;
...
pthread_create(&tid, NULL, function, NULL);
...
pthread_cancel(tid); // отмена потока
void* res;
pthread_join(tid, &res); // ожидание отмены
if (res != PTHREAD_CANCELED)
cout << "Что-то не так!" << endl;Наконец, в QNX (но не в POSIX) существует вызов, подобный
pthread_cancel()
int pthread_abort(pthread_t thread);В отличие от
pthread_cancel()pthread_join()void*PTHREAD_ABORTEDPTHREAD_CANCELEDpthread_cancel()Но и этих мер безопасности недостаточно на все случаи жизни, поэтому механизм потоков предусматривает еще один уровень (механизм) страховки.
Стек процедур завершения
Для поддержания корректности состояния объектов процесса каждый поток может помещать (добавлять) в стек процедур завершения (thread's cancellation-cleanup stack) функции, которые при завершении (
pthread_exit()returnpthread_cancel()
void pthread_cleanup_push(void (routine)(void*), void* arg);где
routineargФункции завершения (начиная с вершины стека) вызываются со своими блоками данных в случаях, когда:
• поток завершается, выполняя
pthread_exit()• активизируется действие отмены потока, ранее запрошенное по вызову
pthread_cancel()• выполняется второй (комплементарный к
pthread_cleanup_push()
void pthread_cleanup_pop(int execute);Этот вызов выталкивает из стека последнюю помещенную туда
pthread_cleanup_push()execute