Простой вызов входа
Задача-клиент осуществляет вызов входа задачи-сервера, идентифицируя как объект задачи-сервера, так и необходимый вход задачи-сервера.
Для демонстрации описаний простых вызовов входов задачи-сервера, заданных в задаче-клиенте, рассмотрим следующий пример:
declare
. . . Simple_Task_Variable : Simple_Task; . . . Read_Value : Integer; Request_Item : Integer; . . . begin . . . Anonimous_Task.Start; . . . Simple_Task_Variable.Read (Read_Value); Simple_Task_Variable.Request (Middle) (Request_Item); . . . end; |
Как видно из этого примера, простые вызовы входов очень похожи на вызовы процедур.
Вызов входа может иметь параметры, значения которых могут передаваться в обоих направлениях между задачей-клиентом и задачей-сервером.
При непосредственной обработке рандеву происходит передача любых параметров "in" и "in out" в задачу-сервер.
Затем задача-сервер выполняет последовательность инструкций, которая расположена внутри инструкции принятия (если такая последовательность существует), а задача-клиент остается в приостановленном состоянии.
Далее, после завершения этой последовательности инструкций, происходит передача любых параметров "out" и "in out" к задаче-клиенту, и обработка рандеву завершается.
После этого обе задачи продолжают свое выполнение независимо друг от друга.
Рассмотрим простой пример программы, которая использует свойства рандеву для своеобразного управления последовательностью запуска задач.
Следует заметить, что стандарт Ады никак не определяет последовательность запуска множества задач одной и той же программы, и язык не предоставляет стандартных средств для непосредственного управления процессом активации множества задач.
Следовательно, разные реализации Ада-систем могут использовать различные правила для определения последовательности активации множества задач, а это означает, что последовательность активации множества задач одной и той же программы может отличаться в различных реализациях Ада-системы.
Однако, используя свойства рандеву, можно программно осуществлять взамную синхронизацию выполнения задач.
Таким образом, выполнение тела задачи может быть приостановлено в самом начале задачи, то есть до того, как задача начнет выполнять свою непосредственную работу.
Такой способ использования рандеву демонстрируется в следующем примере программы:
with Ada.Text_IO; procedure Multitasking_Demo_3 is -- спецификация типа задачи task type Simple_Task (Message: Character; How_Many: Positive) is entry Start; -- этот вход будет использоваться для реального -- запуска задачи на выполнение end Simple_Task; -- тело задачи task body Simple_Task is begin -- для Simple_Task accept Start; -- в этом месте, выполнение задачи будет заблокировано -- до поступления вызова входа for Count in 1..How_Many loop Ada.Text_IO.Put_Line("Hello from Simple_Task " & Message); delay 0.1; end loop; end Simple_Task; -- переменные задачного типа Simple_Task_A: Simple_Task(Message => 'A', How_Many => 5); Simple_Task_B: Simple_Task(Message => 'B', How_Many => 3); begin -- для Multitasking_Demo_3 -- в момент, когда управление достигнет этой точки, -- все задачи начнут свое выполнение, -- но будут приостановлены в инструкциях принятия рандеву Simple_Task_B.Start; Simple_Task_A.Start; end Multitasking_Demo_3; |
Каждая задача имеет вход Start, который используется для управления очередностью запуска задач.
В результате сначала запускается задача Simple_Task_B, а затем Simple_Task_A.
Рассмотрим еще один простой пример программы, в котором демонстрируется использование входов с параметрами.
procedure Demo is X : Duration := Duration(Random(100)); Y : Duration; task Single_Entry is entry Handshake(Me_Wait : in Duration; You_Wait : out Duration); end task; task body Single_Entry is A : Duration := Duration(Random(100)); B : Duration; begin Delay A; accept Handshake(Me_Wait : in Duration; You_Wait : out Duration) do B := Me_Wait; You_Wait := A; end Handshake; Delay B; end; begin Delay(X); Handshake(X, Y); Delay(Y); end Demo; |
Следует заметить, что возможна ситуация, когда задача ожидает рандеву, но при этом нет ни одной задачи, с которой она может его осуществить.
В этом случае задача будет аварийно завершена с исключением Tasking_Error.