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

  • Если задача достигла оператора принятия раньше любого вызова это­го входа, то выполнение задачи приостанавливается до получения такого вызова.

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

Если несколько задач вызывают один и тот же вход до того, как дос­тигнут оператор принятия, то эти вызовы становятся в очередь; с каждым входом связывается одна очередь.. Каждое выполнение оператора принятия удаляет из очереди один вызов. Вызовы обрабатываются в порядке поступ­ления.

При попытке вызвать вход задачи, закончившей свое выполнение, в точке вызова вызывающей задачи возбуждается исключение TASKING—ERROR; это же исключение возбуждается в точке вызова, если вызванная задача заканчивает свое выполнение до принятия входа (см. так­же 9.10 для случая, когда вызванная задача становится аварийной). Исклю­чение CONSTRAINT-ERROR возбуждается, если индекс входа семейства не принадлежит заданному дискретному диапазону.

Примеры описаний входов:

entry ЧИТАТЬ (В: out ЭЛЕМЕНТ);

entry ЗАХВАТИТЬ;

entry ЗАПРОС (УРОВЕНЬ) (Д: ЭЛЕМЕНТ); - - семейство входов

Примеры вызовов входов:

УПРАВЛЕНИЕ. ОСВОБОДИТЬ; - - см. 9.2 и 9.1

ПОСТАВЩИК_ПОТРЕБИТЕЛЬ.ПИСАТЬ (Е); - -см. 9.1

ПУЛ (5) .ЧИТАТЬ (СЛЕДУЮЩИЙ_СИМВ) ; - - см. 9.1 и 9.2

КОНТРОЛЛЕР. ЗАХВАТИТЬ (НИЗКИЙ) (НЕКОТОРЫЙ_ЭЛЕМЕНТ); - - см. 9.1

Примеры операторов принятия:

accept ЗАХВАТИТЬ;

accept ЧИТАТЬ (В: out ЭЛЕМЕНТ) do

В: = ЛОКАЛЬНЫЙ_ЭЛЕМЕНТ;

end ЧИТАТЬ;

accept ЗАПРОС (НИЗКИЙ) (Д: ЭЛЕМЕНТ) do

end ЗАПРОС;

Примечание. Заданный в операторе принятия раздел формальных параметров не предвыполняется; он используется только для идентификации соответствующего входа.

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

Если границы дискретного диапазона семейства входов являются литералами це­лого типа, то индекс (в имени входа или в операторе принятия) должен быть предоп­ределенного типа INTEGER (см. 3.6.1) .

  1. Операторы задержки, длительность и время

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

оператор—Задержки : : = delay простое_выражение;

Простое выражение должно быть предопределенного фиксированного типа DURATION (ДЛИТЕЛЬНОСТЬ); его значение выражается в секундах; оператор задержки с отрицательным значением эквивалентен оператору за­держки с нулевым значением аргумента.

Все реализации типа DURATION должны допускать представление дли­тельности (положительные и отрицательные) по крайней мере до 86400 с (1 сут); минимальная представимая длительность, DURATION'SMALL, должна быть не больше 20 мс (по возможности, значение не превышает 50 мкс. Заметим, что DURATION'SMALL не обязано соответствовать основ­ному циклу таймера, именованному числу SYSTEM.TICK (см. 13.7).

Определение типа TIME (ВРЕМЯ) приведено в предопределенном па­кете CALENDAR (КАЛЕНДАРЬ). Функция CLOCK (ЧАСЫ) возвращает те­кущее значение типа TIME. Функции YEAR, MONTH, DAY и SECONDS (ГОД, МЕСЯЦ, ДЕНЬ и СЕКУНДЫ) возвращают соответствующие наиме­нованиям значения для заданнс^о значения аргумента типа TIME, а процеду­ра SPLIT (СЛОЙ) возвращает одновременно все четыре соответствующих значения. Наоборот, функция TIME_OF (ВРЕМЯ_ИЗ) упаковывает номера года, месяца, числа дня и значение длительности в значение типа TIME. Опе­рации ”+” и для сложения и вычитания значений времени и длительнос­ти, а также операции отношения для значений времени, имеют традицион­ный смысл.

Исключение TIME_ERROR (ОШИБКА_ВРЕМЕНИ) возбуждается в функции TIME_OF, если значения фактических параметров не позволяют сформировать соответствующую дату. Это исключение возбуждается также операциями ”+” и если для заданных операндов они не могут возвра­тить дату с номером года из диапазона соответствующего подтипа или если операция не может возвратить значение из диапазона типа DURATION.

package CALENDAR is

type TIME is private;

subtype YEAR NUMBER is INTEGER range 1901. .2099;

subtype MONTH_NUMBER is INTEGER range 1. .12;

subtype DAY NUMBER is INTEGER range 1. .31;

subtype DAY_DURATION is DURATION range 0.0. .86400.0;

function CLOCK return TIME;

function YEAR (DATE:TIME) return YEAR_NUMBER;

function MONTH (DATE:TIME) return MONTH-NUMBER;

function DAY (DATErTIME) return DAY-NUMBER;

function SECONDS (DATE:TIME) return DAY DURATION;

procedure SPLIT (DATE: in TIME;

YEAR: out YEAR_NUMBER;

MONTH: out MONTH-NUMBER;

DAY: out DAY_NUMBER;

SECONDS: out DAY DURATION);

function TIME_OF (YEAR: YEAR-NUMBER;

MONTH: MONTH-NUMBER;

DAY: DAY_NUMBER;

SECONDS: DAY-DURATION: =0.0) return TIME;

function ”+” (LEFT: TIME; RIGHT: DURATION) return TIME; function(LEFT: DURATION; RIGHT: TIME) return TIME;

function ” (LEFT:TIME; RIGHT: DURATION) return TIME;

function (LEFT:TIME; RIGHT:TIME) return DURATION;

function ”<” (LEFT,RIGHT: TIME) return BOOLEAN;

function ”< = ”(LEFT, RIGHT: TIME) return BOOLEAN;

function ”>” (LEFT, RIGHT: TIME) return BOOLEAN;

function”>=” (LEFT, RIGHT: TIME) return BOOLEAN;

TIME ERROR: exception; - - может быть возбуждено функцией

- - TIME_OF и операциями ”+” и private

  • - зависит от реализации

end;

Примеры:

delay 3.0; - - задержка на 3.0 с

declare

use CALENDAR;

  • - ИНТЕРВАЛ - глобальная константа типа DURATION

СЛЕДУЮЩЕЕ_ВРЕМЯ: TIME: = CLOCK + ИНТЕРВАЛ;

begin

loop

•delay СЛЕДУЮЩЕЕ_ВРЕМЯ - CLOCK;

- - некоторые действия

СЛЕДУЮЩЕЕ_ВРЕМЯ: = СЛЕДУЮЩЕЕ_ВРЕМЯ + ИНТЕРВАЛ;

end loop;

end;

Примечание. Во втором примере цикл повторяется в среднем один раз каждые ИНТЕРВАЛ секунд. Этот интервал между двумя последовательными итерациями толь­ко приблизителен. Однако здесь не произойдет накопление дрейфа во времени, по­скольку длительность каждой итерации (существенно) меньше значения ИНТЕРВАЛ.

  1. . Операторы отбора

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

оператор—отбора : : = отбор_с_ожиданием

I условный—вызов—входа | временной—вызов_входа

  1. .1.Отбор с ожиданием

Эта форма оператора отбора допускает объединение ожидания и отбор одной или нескольких альтернатив. Отбор может зависеть от условий, свя­занных с каждой альтернативой отбора с ожиданием.

отбор_с_ожиданием : : =

select

альтернатива_отбора

{or

альтернатива_отбора }

[else

последовательность—операторов ]

end select;

альтернатива_отбора : ; =

[when условие =>]

альтернатива_отбора_с_ожиданием

альтернатива_отбора_с_ожиданием : : = альтернатива_принятия

I альтернатива_задержки | альтернатива _завершения альтернатива_принятия : : =

оператор_принятия [последовательность_операторов] альтернатива_задержки : : =

оператор_задержки [последовательность_операторов] альтернатива_завершения : : — terminate;

Оператор отбора с ожиданием должен содержать по крайней мере одну альтернативу принятия. В дополнение к этому оператор отбора с ожиданием может содержать либо альтернативу завершения (только одну), либо одну или несколько альтернатив задержки, либо раздел else; эти три возможнос­ти являются взаимоисключающими.

Альтернатива отбора называется открытой, если она не начинается с за­резервированного слова when или если значение условия - TRUE. В против­ном случае альтернатива называется закрытой.

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

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

Отбор других форм альтернатив или раздела else осуществляется сле­дующим образом:

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

  • Отбирается раздел else, выполняется последовательность операторов этого раздела, если нельзя немедленно отобрать альтернативу принятия, в частности, если все альтернативы закрыты.

• Отбирается открытая альтернатива завершения, если перечисленные в разд. 9.4 условия удовлетворены. Из других правил следует, что нельзя ото­брать альтернативу завершения, пока существует очередь вызовов любого входа задачи.

Исключение PROGRAMM_ERROR возбуждается, если все альтернативы закрыты и раздел else отсутствует.

Пример оператора отбора:

select

accept ВЫДАЧА_СИГНАЛА_МАШИНИСТУ;

or

delay 30.0 * СЕКУНД;

ОСТАНОВИТЬ_СОСТАВ;

end select;

Пример тела задачи с оператором отбора:

task body РЕСУРС is

ЗАНЯТ: BOOLEAN: = FALSE;

begin

loop

select

when not ЗАНЯТ =>

accept ЗАХВАТИТЬ do

ЗАНЯТ: = TRUE;

end;

or

accept ОСВОБОДИТЬ do

ЗАНЯТ: = FALSE;

end;

or

terminate;

end select;

end loop;'

end РЕСУРС;

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

  1. Условные вызовы входов

Условный вызов входа производит вызов входа, который отменяется, если рандеву нельзя осуществить немедленно.

условный_вызов_входа : : =

select

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

[послед овательность_операторов ]

else

последовательность_операторов

end select;

При выполнении условного вызова входа вначале вычисляется имя вхо­да. Затем выполняются требуемые вычисления фактических параметров, как при вызове подпрограммы (см. 6.4).

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

Если вызов входа отменен, то выполняются операторы раздела else (по­сле зарезервированного слова else). В противном случае происходит ранде­ву и выполняется последовательность операторов после вызова входа (если она есть).

Выполнение условного вызова входа возбуждает исключение TASKING—ERROR, если вызванная задача уже закончила свое выполнение (см. разд. 9.10 для случая, когда вызванная задача становится аварийной).

Пример:

procedure ОБОРОТ (Р: РЕСУРС) is

begin

loop

select

Р.ЗАХВАТИТЬ;

return;

else;

null; - - занято, надо подождать

end select;

end loop;

end;

  1. В p e M e и и ы e вызовы входов

Временной вызов'входа производит вызов входа, который отменяется, если рандеву не началось на протяжении заданной задержки.

временной—вызов_входа ; : =

select

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

[последовательность—операторов] ог

альтернатива—задержки

end select;

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

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

Выполнение временного вызова входа возбуждает исключение TASKING-ERROR, если вызванная задача закончила свое выполнение до принятия вызова (см. также разд. 9.10 для случая, когда вызванная задача становится аварийной)