Если вызывающая задача перешла к оператору вызова входа раньше, чем имеющая этот вход задача достигла оператора принятия, то выполнение вызывающей задачи приостанавливается.
Если задача достигла оператора принятия раньше любого вызова этого входа, то выполнение задачи приостанавливается до получения такого вызова.
Если вход был вызван и соответствующий оператор принятия достигнут, то его последовательность операторов (если она есть) выполняется вызванной задачей (вызывающая задача остается приостановленной). Это взаимодействие задач называется рандеву. После рандеву вызывающая задача и задача, содержащая вход, продолжают выполняться параллельно.
Если несколько задач вызывают один и тот же вход до того, как достигнут оператор принятия, то эти вызовы становятся в очередь; с каждым входом связывается одна очередь.. Каждое выполнение оператора принятия удаляет из очереди один вызов. Вызовы обрабатываются в порядке поступления.
При попытке вызвать вход задачи, закончившей свое выполнение, в точке вызова вызывающей задачи возбуждается исключение 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) .
Операторы задержки, длительность и время
Выполнение оператора задержки вычисляет простое выражение и приостанавливает дальнейшее выполнение задачи, содержащей оператор задержки по крайней мере на длительность, заданную вычисленным значением.
оператор—Задержки : : = 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;
Примечание. Во втором примере цикл повторяется в среднем один раз каждые ИНТЕРВАЛ секунд. Этот интервал между двумя последовательными итерациями только приблизителен. Однако здесь не произойдет накопление дрейфа во времени, поскольку длительность каждой итерации (существенно) меньше значения ИНТЕРВАЛ.
. Операторы отбора
Существует три формы операторов отбора. Одна форма обеспечивает отбор с ожиданием из одной или нескольких альтернатив. Две другие обеспечивают условный и временной вызовы входа.
оператор—отбора : : = отбор_с_ожиданием
I условный—вызов—входа | временной—вызов_входа
.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 РЕСУРС;
Примечание. В отборе с ожиданием допускаются несколько открытых альтернатив задержки или несколько открытых альтернатив принятия одного и того же входа.
Условные вызовы входов
Условный вызов входа производит вызов входа, который отменяется, если рандеву нельзя осуществить немедленно.
условный_вызов_входа : : =
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;
В p e M e и и ы e вызовы входов
Временной вызов'входа производит вызов входа, который отменяется, если рандеву не началось на протяжении заданной задержки.
временной—вызов_входа ; : =
select
оператор _вызова_входа
[последовательность—операторов] ог
альтернатива—задержки
end select;
При выполнении временного вызова входа вначале вычисляется имя входа». Затем выполняются требуемые вычисления фактических параметров, как при вызове подпрограммы (см. разд. 6.4). После этого вычисляется выражение, задающее задержку, и, наконец, производится вызов входа.
Если рандеву может начаться в течение указанной длительности (или немедленно, как для условного вызова входа, если задержка отрицательная или нулевая), то оно происходит, и затем после вызова входа выполняется последовательность операторов (если она есть). В противном случае по истечении заданной длительности вызов входа отменяется и выполняется возможная последовательность операторов альтернативы задержки.
Выполнение временного вызова входа возбуждает исключение TASKING-ERROR, если вызванная задача закончила свое выполнение до принятия вызова (см. также разд. 9.10 для случая, когда вызванная задача становится аварийной)