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

Простой вызов входа


Задача-клиент осуществляет вызов входа задачи-сервера, идентифицируя как объект задачи-сервера, так и необходимый вход задачи-сервера.

Для демонстрации описаний простых вызовов входов задачи-сервера, заданных в задаче-клиенте, рассмотрим следующий пример:

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;

Как видно из исходного текста этого примера, здесь описаны два объекта задач: Simple_Task_A и Simple_Task_B.

Каждая задача имеет вход 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;

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

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

В этом случае задача будет аварийно завершена с исключением Tasking_Error.


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