Литмир - Электронная Библиотека
Содержание  
A
A

 exit(EXIT_FAILURE);

}

Когда вы запустите программу, то получите следующий вывод:

$ <b>./thread6</b>

Waiting for thread to say it's finished...

thread_function is running. Argument was Hello World

Waiting for thread to say it's finished...

Waiting for thread to say it's finished...

Waiting for thread to say it's finished...

Second thread setting finished flag, and exiting now

Other thread finished, bye!

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

Этот пример очень похож на установку атрибута отсоединенного состояния за исключением того, что вы задаете вместо него способ планирования.

Отмена потока

Иногда требуется, чтобы один поток попросил другой завершиться досрочно способом, очень похожим на отправку ему сигнала. Сделать это можно с помощью потоков и параллельно с помощью обработки сигнала; у потоков появляется возможность изменить свое поведение, когда их просят завершиться.

Давайте сначала рассмотрим функцию для создания запроса на завершение потока.

<b>#include &lt;pthread.h&gt;</b>

<b>int pthread_cancel(pthread_t thread);</b>

Она достаточно проста: имея идентификатор потока, вы можете запросить его аннулирование. На приемном конце запроса на отмену все немного сложнее, но не слишком. Поток может установить состояние отмены с помощью функции

pthread_setcancelstate
.

<b>#include &lt;pthread.h&gt;</b>

<b>int pthread_setcancelstate(int state, int *oldstate);</b>

Первый параметр равен либо значению

PHTREAD_CANCEL_ENABLE
, позволяющему получать запросы на отмену, либо
PTHREAD_CANCEL_DISABLE
, заставляющему игнорировать подобные запросы. Указатель
oldstate
дает возможность получить предыдущее состояние. Если оно вас не интересует, можно просто передать в этом параметре
NULL
. Если запросы на отмену принимаются, есть второй уровень управления, принимаемый потоком, — тип отмены, который задается функцией
pthread_setcanceltype
.

<b>#include &lt;pthread.h&gt;</b>

<b>int pthread_setcanceltype(int type, int *oldtype);</b>

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

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 &lt;stdio.h&gt;

#include &lt;unistd.h&gt;

#include &lt;stdlib.h&gt;

#include &lt;pthread.h&gt;

void *thread_function(void *arg);

int main() {

 int res;

 pthread_t a_thread;

 void *thread_result;

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

 if (res != 0) {

  perror(&quot;Thread creation failed&quot;);

  exit(EXIT_FAILURE);

 }

 sleep(3);

 printf(&quot;Canceling thread...\n&quot;);

 res = pthread_cancel(a_thread);

 if (res != 0) {

  perror(&quot;Thread cancelation failed&quot;);

  exit(EXIT_FAILURE);

 }

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

 res = pthread_join(a_thread, &amp;thread_result);

 if (res != 0) {

  perror(&quot;Thread join failed&quot;);

  exit(EXIT_FAILURE);

 }

 exit(EXIT_SUCCESS);

}

void *thread_function(void *arg) {

 int i, res;

 res = pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);

 if (res != 0) {

225
{"b":"285844","o":1}