QNX/UNIX: Анатомия параллелизма
Шрифт:
А вот один из многих допустимых вариантов:
Недостатком
Уничтожение (отмена) потока
Корректное завершение выполняющегося потока «извне», из другого потока (то есть асинхронно относительно прерываемого потока), — задача отнюдь не тривиальная; она намного сложнее аналогичной задачи прерывания процесса. Это связано с обсуждавшимся ранее при рассмотрении завершения потоков временем жизни объектов, которые могут быть использованы потоком к моменту его отмены (блоки динамической памяти, файловые дескрипторы, примитивы синхронизации и другие объекты системы).
Если для процесса в перечень «опасных» (с точки зрения завершения) объектов включаются только объекты со временем жизни выше уровня процесса (их число достаточно ограничено), то для потока в число таких объектов включаются уже все объекты со временем жизни процесса (process-persistent). Завершающийся (покидающий процесс) поток обязан оставить все объекты процесса в состоянии, пригодном для их дальнейшего использования другими потоками процесса.
Далее мы подробно рассмотрим то множество предосторожностей, которыми «обложена» отмена потока. Однако именно по причине их «множества» стоит сформулировать краткое правило: не пытайтесь завершать поток извне его функции потока, если для этого нет в высшей степени обоснованной необходимости (а такая необходимость действительно бывает, но крайне редко). Даже в крайнем случае следует рассмотреть возможность вместо отмены потока послать ему сигнал (даже не только «сигнал UNIX», а в более широком смысле — «некоторое сообщение»), который, обрабатываясь в контексте потока, после корректных завершающих действий вызовет его завершение. (Как обращаться с сигналами в потоке, будет детально рассмотрено позже.)
Для отмены (принудительного завершения) потока используется вызов:
где в качестве параметра thread указывается TID отменяемого потока. Однако этот вызов не отменяет поток, а только запрашивает завершение потока. В зависимости от статуса отмены, который мы сейчас рассмотрим, поток может перейти (или нет) к действию завершения, которое состоит в том, что:
• выполняются все процедуры завершения, занесенные ранее в стек завершения вызовами
• выполняются деструкторы собственных данных потока;
• отменяемый поток завершается;
• процесс отмены — асинхронный с точки зрения вызывающего
Прежде всего, поток может вообще отказаться выполнять любые отмены, вызвав из своей функции потока:
где
Далее, даже если для потока установлено состояниезавершаемости (также называемое «состоянием отмены»)
где
Обе рассмотренные функции установок [23] параметров отмены при успешном выполнении возвращают значение EOK.
Итак, действия потока на запрос его завершения будут определяться текущей комбинацией двух установленных для него параметров: состоянием и типом отмены.
Теперь о том, чем же отличается отмена асинхронно и синхронно завершаемых потоков. Поток с асинхронным типом отмены (установленный с
23
Согласно стандарту POSIX установки состояния и типа завершаемости могут быть сделаны только из уже выполняющегося кода потока (при старте потока эти параметры установлены в значения по умолчанию). QNX делает расширение, позволяя установить соответствующие флаги в атрибутной записи еще до создания потока. Подробнее об этом говорилось при обсуждении создания потока.
Каждый вызов
( Очень важно!) Достаточно много библиотечных функций могут сами устанавливать точки отмены. Более того, такие функции могут косвенно вызываться из других функций в программе и тем самым неявно устанавливать точки отмены. Информацию о таких функциях следует искать в справочной man-странице по функции