Если алгоритм требует запоминания и переименования задачи, то это можно сде­лать определением ссылочного типа, указывающего на соответствующие заданные объекты, и использованием ссылочных значений для целей идентификации (см. преды­дущий пример). Присваивание для такого ссылочного типа возможно, как и для лю­бого другого ссылочного типа.

Для заданных типов допустимы описания подтипов, как и для других типов, но никакие ограничения к заданному типу не применимы.

  1. Выполнение и активизация задачи

Тело задачи определяет выполнение всякой задачи, которая указывает­ся заданным объектом соответствующего задачного типа. Начальный этап этого выполнения называется активизацией заданного объекта и указанной им задачи; активизация состоит из предвыполнения раздела описаний (если он есть) тела задачи. Выполнение различных задач, в частности, их активиза­ция, производится параллельно.

Если задачный объект описан непосредственно в разделе описаний, то активизация задачного объекта начинается после предвыполнения раздела описаний, предшествующего зарезервированному слову begin; аналогично, если такое описание помещено непосредственно в спецификацию пакета, то активизация начинается после предвыполнения раздела описаний тела паке­та. То же относится и к активизации задачного объекта, являющегося под­компонентом объекта, описанного непосредственно в разделе описаний или спецификации пакета. Первый оператор, следующий за разделом описаний, выполняется только после окончания активизации заданных объектов.

Если при активизации одной из таких задач возбуждается исключение, то эта задача становится законченной (см. 9.4); на других задачах это пря­мо не отражается. Если во время своей активизации одна из этих задач ста­новится законченной, то после завершения (успешного или нет) активиза­ции всех задач возбуждается исключение TASKING_ERROR; исключение возбуждается непосредственно за разделом описаний перед выполнением первого оператора (непосредственно после зарезервированного слова be­gin ). Исключение TASKING_ERROR возбуждается лишь однажды, даже если во время активизации сразу несколько задач становятся законченны­ми таким способом.

Если исключение возбуждается при предвыполнении раздела описаний или спецификации пакета, то любая созданная (прямо или косвенно) этим предвыполнением задача, которая еще не активизирована, становится завер­шенной, и, таким образом, она никогда не активизируется (см. разд. 9.4 с определением завершенной задачи).

Приведенные выше правила предполагают, что в теле пакета без опера­торов присутствует пустой оператор. Для пакета без тела подразумевается тело пакета с единственным пустым оператором. Если пакет без тела описы­вается непосредственно в некотором программном модуле или в операторе блока, то его тело подразумевается в конце раздела описаний программно­го модуля или оператора блока; при наличии нескольких пакетов без тела порядок следования подразумеваемых тел пакетов неопределен.

Задачный объект, являющийся объектом или подкомпонентом объек­та, созданного выполнением генератора, активизируется этим выполнени­ем. Активизация начинается после инициализации объекта, созданного гене­ратором; если несколько подкомпонентов являются заданными объектами, они активизируются параллельно. Ссылочное значение, указывающее этот объект, возвращается генератором только после проведения этих активи­заций.

Если исключение возбуждается при активизации одной из таких задач, то она становится законченной задачей; на другие задачи этот факт не ока­зывает прямого воздействия. Если во время своей активизации одна из этих задач становится законченной таким образом, то после проведения (успешного или нет) активизации всех этих задач возбуждается исключение TASKING_ERROR; исключение возбуждается в той точке программы, где выполняется генератор. Исключение TASKING_ERROR возбуждается лишь однажды, даже если во время активизации сразу несколько задач становят­ся законченными таким образом.

Если исключение возбуждается во время инициализации объекта, соз­данного генератором (следовательно, до начала активизации), то любая за­дача, указанная подкомпонентом этого объекта, становится завершенной, и, таким образом, она никогда не активизируется.

Пример:

procedure Р is

А, В: РЕСУРС; - - предвыполняет заданные объекты А и В

С: РЕСУРС; - - предвыполняет заданный объект С

begin

  • - задачи А, В, С активизируются параллельно

  • - перед выполнением первого оператора

end;

Примечание. Вход задачи может быть вызван до активизации задачи. Если несколько задач активизируются параллельно, выполнение любой из них не предпола­гает ожидания конца активизации других задач. Задача может стать законченной во время ее активизации как из-за исключения, так и из-за прекращения (см. 9.10).

  1. Зависимость и завершение задач

Каждая задача зависит по крайней мере от одного родителя. Родитель - это конструкция, являющаяся либо задачей, либо в данный момент выпол­няемым оператором блока или подпрограммой, либо библиотечным паке­том (но не описанным в другом программном модуле). Зависимость от ро­дителя является непосредственной зависимостью в следующих двух слу­чаях:

  1. Задача, указанная заданным объектом, который является объектом или подкомпонентом объекта, созданными при выполнении генератора, за­висит от родителя, предвыполняющего соответствующее описание ссылоч­ного типа.

  2. Задача, указанная другим заданным объектом, зависит от родителя, выполнение которого создает заданный объект.

Более того, если задача зависит от данного родителя, являющегося опе­ратором блока, выполняемым Другим родителем, то задача также косвенно зависит и от этого родителя; то же справедливо, если данный родитель яв­ляется подпрограммой, вызванной другим ррдителем, а также если данный родитель — задача, зависящая (прямо или косвенно) от другого родителя. Зависимости существуют и для объектов личного типа, полное описание ко­торого задано в терминах заданного типа.

Говорят, что задача закончила свое выполнение, когда осуществилось выполнение последовательности операторов, помещенных в ее теле за ре­зервированным словом begin. Аналогично этому, блок или подпрограмма закончили свое выполнение, когда осуществилось выполнение соответству­ющей последовательности операторов. В случае оператора блока также го­ворят, что выполнение его закончилось при достижении операторов выхода, возврата или перехода, передающих управление из блока. В случае процеду­ры также говорят, что ее выполнение закончилось при достижении соответ­ствующего оператора возврата. В случае функции также говорят, что ее вы­полнение закончилось после вычисления результирующего выражения в операторе возврата. Наконец, выполнение задачи, оператора блока или под­программы закончено, если при выполнении содержащихся в них соответ­ствующих последовательностей операторов возбуждено исключение и нет соответствующего ему обработчика, а при его наличии — по окончании вы­полнения соответствующего обработчика.

Если у задачи нет зависимых задач и закончено ее выполнение, имеет место ее завершение. После завершения говорят, что она завершена. Если задача имеет зависимые задачи, то ее завершение имеет место после оконча­ния выполнения задачи и завершения всех зависимых задач. Из оператора блока или тела подпрограммы, чье выполнение закончено, нельзя выйти до завершения всех зависимых задач.

С другой стороны, завершение задачи имеет место тогда и только тог­да, когда ее выполнение достигло открытой альтернативы завершения в операторе отбора (см. 9.7.1) и удовлетворены Следующие условия:

  • Задача зависит от некоторого родителя, выполнение которого закон­чено (следовательно, не от библиотечного пакета).

  • Каждая задача, зависящая от рассмотренного родителя, либо уже за­вершена, либо также ожидает открытой альтернативы завершения в опера­торе отбора.

Когда оба условия удовлетворены, задача становится завершенной вместе со всеми задачами, зависящими от этого же родителя.

Пример:

declare

type ГЛОБАЛЬНЫЙ is access РЕСУРС; - - см. 9.1

А, В: РЕСУРС;

Г: ГЛОБАЛЬНЫЙ;

begin

- - активизация А и В declare

type ЛОКАЛЬНЫЙ is access РЕСУРС;

X: ГЛОБАЛЬНЫЙ: = new РЕСУРС; - - активизация X. all

Л: ЛОКАЛЬНЫЙ: = new РЕСУРС; - - активизация Л. all

С: РЕСУРС;

begin

- - активизация С

Г: = X; - - Г и X указывают один и тот же заданный объект

end; - - ожидание завершения С и Л. all, но не X. all

end; - - ожидание завершения А, В и Г. all

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

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

Для ссылочного типа, являющегося производным другого ссылочного типа, соот­ветствующее определение ссылочного типа является определением родительского ти­па; зависимость в данном случае является зависимостью от родителя, который пред- выполняет основные определения родительского ссылочного типа.

Описание переименования вводит новое имя для уже существующего понятия, и, следовательно, не порождает дальнейшей зависимости.

  1. Входы, вызовы входов и операторы принятия

Вызовы входов и операторы принятия являются основными средства­ми синхронизации задач и передачи значений между задачами. Описание вхо­да подобно описанию подпрограммы и допустимо только в спецификации задачи. Действия, которые следует выполнить после вызова входа, задаются соответствующими операторами принятия.

описание_входа : : =

entry идентификатор [ (дискретный диапазон) ] [раздел_формальных_параметров]

оператор_вызова_входа : : =

имя_входа [раздел_фактических_параметров];

оператор_принятия : : =

accept простое_имя_входд [ (индекс_входа) ] [раздел_формальных_параметров] [do последовательность_операторов

end [простое_имя_входа] ] ;

индекс_входа : : = выражение

Описание входа, включающее дискретный диапазон (см. разд. 3.6.1), описывает семейство различных входов с одним и тем же разделом фор­мальных параметров (если он есть), а именно по одному входу для каж­дого значения дискретного диапазона. Термин одиночный вход использует­ся при определении правил, применимых к любому входу, отличному от члена семейства. Задача, указанная объектом задачного типа, имеет вход (входы), который (которые) описан (описаны) в спецификации этого за­дачного типа.

В теле задачи каждый из ее одиночных входов или семейства входов может быть именован соответствующим простым именем. Имя входа се­мейства записывается в форме индексируемого компонента: за простым именем семейства в круглых скобках следует индекс; тип этого индекса должен быть тем же, что и тип дискретного диапазона в соответствующем описании семейства входов. Вне тела задачи имя входа записывается в фор­ме именованного компонента, префикс которого обозначает задачный объ­ект, а постфикс является простым именем ОДНОГО из одиночных входов или семейства входов.

Одиночный вход совмещается с подпрограммой, литералом перечисле­ния или другим одиночным входом, если у них одинаковые идентификато­ры. Совмещение для семейств входов не определено. Одиночный вход или вход семейства могут быть переименованы в процедуру, как поясняется в разд. 8.5.

Виды параметров, определенные для параметров формального раздела описания входа, такие же, как в описании подпрограммы, и имеют тот же смысл (см. 6.2). Синтаксически оператор вызова входа подобен оператору вызова процедуры; правила сопоставления параметров остаются теми же, что и для вызовов подпрограмм (см. 6.4.1 и 6.4.2).

Оператор принятия задает действия, которые выполняются при вызове упомянутого в этом операторе входа (им может быть и вход семейства). Раздел формальных параметров оператора принятия должен быть согласо­ван с разделом формальных параметров, заданным в описании одиночного входа или семейства входов, упомянутых в операторе принятия (см. разд. 6.3.1 о согласовании). Если в конце оператора принятия используется прос­тое имя, оно должно повторять простое имя, заданное в начале этого опера­тора.

Оператор принятия входа данной задачи допускается только в соответ­ствующем теле задачи, исключая тело программного модуля, вложенного в тело задачи, и другой оператор принятия этого же одиночного входа или входа того же семейства. (Из этих правил следует, что задача может выпол­нять операторы принятия только своих входов). Тело задачи может содер­жать несколько операторов принятия одного и того же входа.

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

Выполнение оператора принятия начинается с вычисления индекса вхо­да (в случае входа семейства) . Выполнение оператора вызова входа начина­ется с вычисления имени входа, затем следуют вычисления, требуемые для фактических параметров, как и при вызове подпрограммы (см. 6.4). Даль­нейшее выполнение оператора принятия и соответствующего оператора вы­зова входа синхронизировано.

Если данный вход вызывается только одной задачей, то предоставляют­ся две возможности: