Вход/Регистрация
QNX/UNIX: Анатомия параллелизма
вернуться

Цилюрик Олег Иванович

Шрифт:

Далее, даже если для потока установлено состояниезавершаемости (также называемое «состоянием отмены»)

PTHREAD_CANCEL_ENABLE
(это значение по умолчанию при создании потока), поток может переопределить еще и типотмены, вызвав:

int pthread_setcanceltype(int type, int* oldtype);

где

type
и
oldtype
— как и в предыдущем случае, новое и ранее установленное значения типа отмены потока, которые могут принимать значения
PTHREAD_CANCEL_ASYNCHRONOUS
(асинхронный по отмене поток) либо
PTHREAD_CANCEL_DEFERRED
(синхронный по отмене поток). Значением по умолчанию, устанавливаемым при создании потока, является
PTHREAD_CANCEL_DEFERRED
, хотя предписываемым POSIX умолчанием является
PTHREAD
_CANCEL_ASYNCHRONOUS.

Обе рассмотренные функции установок [23] параметров отмены при успешном выполнении возвращают значение EOK.

Итак, действия потока на запрос его завершения будут определяться текущей комбинацией двух установленных для него параметров: состоянием и типом отмены.

Теперь о том, чем же отличается отмена асинхронно и синхронно завершаемых потоков. Поток с асинхронным типом отмены (установленный с

PTHREAD_CANCEL_ASYNCHRONOUS
) может быть отменен в любой произвольный момент времени, то есть он всегда «свободен» для отмены и отмена производится немедленно. Поток с синхронным типом отмены (установленный с
PTHREAD_CANCEL_DEFERRED
) может быть остановлен только в тех точках выполнения потока, когда ему «удобно», и соответствующие места в программе называются точками отмены. При поступлении запроса на отмену такого потока (после выполнения извне
pthread_cancel
) запрос помещается в очередь, а процесс отмены активизируется только после того, как отменяемый поток в ходе своего выполнения достигнет очередной точки отмены. Как определяются (создаются) точки отмены в коде потока? Для этого служит функция:

23

Согласно стандарту POSIX установки состояния и типа завершаемости могут быть сделаны только из уже выполняющегося кода потока (при старте потока эти параметры установлены в значения по умолчанию). QNX делает расширение, позволяя установить соответствующие флаги в атрибутной записи еще до создания потока. Подробнее об этом говорилось при обсуждении создания потока.

void pthread_testcancel(void);

Каждый вызов

pthread_testcancel
тестирует очередь поступивших запросов на отмену на предмет наличия запросов, и если таковой запрос есть, процесс отмены активизируется. Если в коде отсутствуют вызовы
pthread_testcancel
, то в нем практически отсутствуют точки отмены и поток становится неотменяемым (подобно установке его состояния отмены в
PTHREAD_CANCEL_DISABLE
). Поэтому при выполнении длительных вычислений функцию
pthread_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_ABORTED
(аналогично возвращается константа
PTHREAD_CANCELED
при выполнении
pthread_cancel
).

  • Читать дальше
  • 1
  • ...
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

Подпишитесь на рассылку: