Rendezvous ADA - 它的工作原理

时间:2014-05-14 07:18:52

标签: task ada multitasking

我试图了解ADA中的R-V如何工作:

服务器(伪)代码:

task test is
  entry put (num: in integer);
  entry get (num: out integer);
end test;

task body test is
  local_num: integer;
begin
  accept put (num: in integer) do
    local_num := num;
  end put;

  // some next processing of local_num, eg:
  local_num := local_num * 2;

  accept get (num: out integer) do
    num := local_num;
  end get;
end test;

和服务器正在进行通信的客户端如下:

client (a)    | server (b)
================================
              |   // sleep
(call_entry)  |   // sleep
a.put(num)    |   // sleep
  // sleep    | (accept_entry)
  // sleep    | b.accept put(num)
  // sleep    | local_num := num;
  // sleep    | local_num := local_num * 2;
              |   ???   <--------------------- what is happening after that point?
(call_entry)  |   // sleep
a.get(num)    |   // sleep
  // sleep    | (accept_entry)
  // sleep    | b.accept get(num)
  • 这是对的吗?
  • 你能描述一下它是如何继续的吗?
  • 谁唤醒了客户以获得结果?客户如何知道,它可以得到结果?

更新:(正确的流程?)

client        | server (test)
================================
test.put(num) |   // sleep      ----------> call entry
test.get(A)   | accept put(num) ----------> accept entry PUT (call entry GET to the QUEUE)
  // sleep    | local_num := num;
  // sleep    | local_num := local_num * 2;
test.get(A)   | accept get(A)   ----------> accept entry (removed from the QUEUE)
              |   // sleep

1 个答案:

答案 0 :(得分:3)

Ada Rendez-Vous非常简单,实际上您有一个任务test,其中有两个条目getput。运行程序后,test任务启动,因此创建local_num值(没有定义的初始值)并执行body但是第一个语句是{accept 1}}所以任务正在等待进入呼叫。

procedure ... is

    task test is 
       ...
    end test ;

    task body test is
       ...
    end test ;

    A : Integer ;

begin
    -- 1. The 'test' task is started here, waiting for a call to `put`
    -- 2. You call the 'put' entry, which mean that the current task (the main task) 
    --    is stopped until the end of the entry call.
    test.put(33) ;
    -- 3. Here the entry 'put' is finished, so the 2 tasks are executing
    --    simultaneously
    -- 4. Here we call the 'get' entry, there is a non predictive behaviour: 
    --    We do not know if the instruction local_num := local_num * 2; has
    --    been executed or not, so 2 case:
    --     - The instruction has been executed, so the 'test' task is waiting
    --       and directly accept the 'get' entry, while the main task wait
    --     - The instruction has not been executed, so the main 'task' wait
    --       until there is someone to accept is call
    --    What you're sure is that the entry 'get' won't be executed before
    --    the instruction, and that someone calling 'get' will have to wait
    --    until the 'test' task get to the 'accept get' instruction.
    test.get(A) ;
    -- 5. Here, the 'get' entry is finished, so you're sure that you have ended
    --    the 'test' task

end ... ;

实际上,当您调用类似test.get的条目时,您将松开控件,直到test.get条目完全执行。如果没有任务等待此条目,您将等到任务请求此条目。

procedure BadTask is

    -- Stupid task that will accept a 'put' entry and then a 'get' (only once)
    task T is
        entry get (A : out Integer);
        entry put (A : in Integer);
    end T ;

    task body T is
        LocalInteger : Integer := 0 ;
    begin
        accept put (A : in Integer) do
            LocalInteger := A ;
        end put ;
        accept get (A : ouInteger) do
            A := LocalInteger ;
        end get ;
    end T ;

    A : Integer ;
begin
    -- Here T is waiting for 'put'
    T.get (A) ; 
    -- You will never get here and your program is blocked because the two tasks
    -- are waiting but no one can't get the control.
end BadTask ;