Ада-95. Компилятор GNAT
66ac8edd

Селекция вызова рандеву


Инструкции отбора select

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

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

Рассмотрим простой пример инструкции отбора для выполнения условного вызова рандеву на входе Service_1

задачи-сервера Server_Task:

select

Server_Task.Service_1 [ параметры для Service_1 ] ; else

Put_Line ("Server_Task is busy!"); end select;

В этом случае, если задача-сервер Server_Task не готова к немедленному приему рандеву на входе Service_1, то вызов рандеву будет отменен и выполнится последовательность инструкций в разделе else, которая выводит сообщение "Server_Task is busy!".

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

Таким образом, общий вид ее применения может быть следующм:



loop

select

Server_Task.Service_1 [ параметры для Service_1 ] ; . . . -- опциональная последовательность инструкций, exit; -- выполняемая после рандеву else

. . . -- последовательность инструкций, -- выполняемая в случае невозможности -- осуществления рандеву end select;

end loop;

Инструкция отбора для временного вызова рандеву позволяет задавать ожидание принятия рандеву на входе задачи-сервера в течение заданного интервала времени.

Пример такой инструкции для выполнения временного вызова рандеву на входе Service_1

задачи-сервера Server_Task

может иметь следующий вид:

select

Server_Task.Service_1 [ параметры для Service_1 ] ; or

delay 5.0; Put_Line ("Server_Task has been busy for 5 seconds!"); end select;

В данном случае, если в течение указанного интервала времени (здесь задан относительный интервал времени длительностью 5 секунд) задача-сервер Server_Task не приняла рандеву на входе Service_1, то вызов рандеву отменяется и выполняется последовательность инструкций, заданная альтернативой задержки, которая в этом примере выдаст сообщение "Server_Task has been busy for 5 seconds!".




Вместо относительного интервала может быть указано абсолютное значение времени:

select

Server_Task.Service_1 [ параметры для Service_1 ] ; or

delay until Christmas; Put_Line ("Server_Task has been busy for ages!"); end select;

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

Инструкция отбора для временного вызова рандеву удобно использовать в качестве сторожевого таймера.

Таким образом, ее общий вид может быть следующм:

loop

select

Server_Task.Service_1 [ параметры для Service_1 ] ; . . . -- опциональная последовательность инструкций, exit; -- выполняемая после рандеву or

delay интервал_времени

. . . -- последовательность инструкций, -- выполняемая в случае невозможности -- осуществления рандеву end select;

end loop;

Заметим, что вместо конструкции "delay интервал_времени", задающей относительный интервал, может быть использована конструкция "delay until интервал_времени", которая указывает абсолютное значение времени.

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

Пример использования такой инструкции может иметь следующий вид:

select

delay 5.0; Put_Line ("Server_Task is not serviced the Service_1 yet"); then abort

Server_Task.Service_1 [ параметры для Service_1 ] ; end select;

В данном случае начинается выполнение инструкций, расположенных между "then abort" и "end select", то есть вызов рандеву с задачей-сервером Server_Task на входе Service_1.

При этом, если истечение интервала времени из инструкции delay (или delay until), расположенной после select, произойдет раньше завершения выполнения Server_Task.Service_1, то выполнение Server_Task.Service_1 принудительно прерывается и выполняется вывод сообщения "Server_Task is not serviced the Service_1 yet".

Примечательно, что использование асинхронной передачи управления не ограничено многозадачностью, например:

select

delay 5.0; Put_Line ("So_Big_Calculation abandoned!"); then abort

So_Big_Calculation; end select;

В данном случае использование асинхронной передачи позволяет прервать неопределенно долго выполняющуюся или "зависшую" в бесконечном цикле процедуру So_Big_Calculation.

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


Содержание раздела