Чтение онлайн

ЖАНРЫ

Основы программирования в Linux
Шрифт:

#include <pthread.h>

int pthread_setcanceltype(int type, int *oldtype);

Тип отмены может принимать одно из следующих значений:

PTHREAD_CANCEL_ASYNCHRONOUS
, заставляющее обрабатывать запросы на отмену немедленно, и
PTHREAD_CANCEL_DEFERRED
, заставляющее запросы на отмену ждать, пока поток не выполнит одну из следующих функций:
pthread_join
,
pthread_cond_wait
,
pthread_cond_timedwait
,
pthread_testcancel
,
sem_wait
или
sigwait
.

Мы не описываем все эти функции в данной главе, поскольку, как правило, не все они нужны. Когда они понадобятся, вы сможете найти дополнительную информацию на страницах интерактивного справочного руководства.

Примечание

В соответствии со стандартом POSIX системные вызовы, способные задерживать выполнение, такие как

read
,
wait
и т.д., должны также быть точками отмены потока. Во время написания книги поддержка этого стандарта в ОС Linux представлялась незавершенной. Но кое-какая работа была проделана, скажем, некоторые задерживающие вызовы, такие как
sleep
, на самом деле допускают отмену. Для того чтобы обезопасить себя, добавляйте вызовы
pthread_testcancel
в программный код, который по вашим расчетам может быть отменен.

Параметр

oldtype
позволяет получить предыдущее состояние, если оно вас не интересует, можно передать
NULL
. По умолчанию потоки запускаются с состоянием отмены, равным
PTHREAD_CANCEL_ENABLE
, и типом отмены —
PTHREAD_CANCEL_DEFERRED
.

Выполните упражнение 12.7.

Упражнение 12.7. Отмена потока

Программа thread7.c — ещё один потомок программы thread1.с. На этот раз основной поток отправляет запрос на отмену потока, который он создал.

#include <stdio.h>

#include <unistd.h>

#include <stdlib.h>

#include <pthread.h>

void *thread_function(void *arg);

int main {

 int res;

 pthread_t a_thread;

 void *thread_result;

 res = pthread_create(&a_thread, NULL, thread_function, NULL);

 if (res != 0) {

perror("Thread creation failed");

exit(EXIT_FAILURE);

 }

 sleep(3);

 printf("Canceling thread...\n");

 res = pthread_cancel(a_thread);

 if (res != 0) {

perror("Thread cancelation failed");

exit(EXIT_FAILURE);

 }

 printf("Waiting for thread to finish...\n");

 res = pthread_join(a_thread, &thread_result);

 if (res != 0) {

perror("Thread join failed");

exit(EXIT_FAILURE);

 }

 exit(EXIT_SUCCESS);

}

void *thread_function(void *arg) {

 int i, res;

 res = pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);

 if (res != 0) {

perror("Thread pthread_setcancelstate failed");

exit(EXIT_FAILURE);

 }

 res = pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);

 if (res != 0) {

perror{"Thread pthread_setcanceltype failed");

exit(EXIT_FAILURE);

 }

 printf("thread_function is running\n");

 for(i = 0; i < 10; i++) {

printf("Thread is still running (%d)...\n", i);

sleep(1);

 }

 pthread_exit(0);

}

Когда

вы выполните эту программу, то увидите следующий вывод, демонстрирующий отмену потока:

$ ./thread7

thread_function is running

Thread is still running (0)...

Thread is still running (1)...

Thread is still running (2)...

Canceling thread...

Waiting for thread to finish...

$

Как это работает

После того как новый поток был создан обычным способом, основной поток засыпает (чтобы дать новому потоку время для запуска) и затем отправляет запрос на отмену потока.

sleep(3);

printf("Cancelling thread...\n");

res = pthread_cancel(a_thread);

if (res != 0) {

 perror("Thread cancelation failed");

 exit(EXIT_FAILURE);

}

В созданном потоке вы сначала задаете состояние отмены, чтобы разрешить отмену потока:

res = pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);

if (res != 0) {

 perror("Thread pthread_setcancelstate failed");

 exit(EXIT_FAILURE);

}

Далее вы задаете тип отмены

PTHREAD_CANCEL_DEFERRED
:

res = pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);

if (res != 0) {

 perror("Thread pthread_setcanceltype failed");

 exit(EXIT_FAILURE);

}

И в конце поток ждет отмену:

for (i = 0; i < 10; i++) {

 printf("Thread is still running (%d)...\n", i);

 sleep(1);

Поделиться с друзьями: