Ada中的嵌套选择

Ada中的嵌套选择,ada,Ada,我在ADA中解决有界缓冲区问题时遇到了一个问题(我在ADA编程中是非常新的) 我有两个任务(我们称之为A和B)可以写入缓冲区,还有一个任务可以从缓冲区(C)读取。此时任务A将两个整数插入缓冲区,而任务B仅插入一个整数。在从缓冲区读取数据之前,任务C需要确定哪个任务(A或B)最后一次将数据插入缓冲区,如果是A,则读取两个最后插入的整数,否则只读取一个 这就是我试图实现缓冲区任务的方式,我想知道这样做是否正确: task bbuffer is N : constant Integer :=

我在ADA中解决有界缓冲区问题时遇到了一个问题(我在ADA编程中是非常新的)

我有两个任务(我们称之为A和B)可以写入缓冲区,还有一个任务可以从缓冲区(C)读取。此时任务A将两个整数插入缓冲区,而任务B仅插入一个整数。在从缓冲区读取数据之前,任务C需要确定哪个任务(A或B)最后一次将数据插入缓冲区,如果是A,则读取两个最后插入的整数,否则只读取一个

这就是我试图实现缓冲区任务的方式,我想知道这样做是否正确:

task bbuffer is 
    N : constant Integer := 20;
    buffer : array(0..N-1) of Integer;
    pointer : Integer range 0..N-1;
    count : Integer range 0..N;
    flag : Integer range 0..1;

    begin
        loop
            select 
                when count < N =>
                    accept PutOne(v:in Integer) do
                        buffer((pointer+count) mod N) := v;
                        count:=count+1;
                    end Put;
            or
                when count < N-1 =>
                    accept PutTwo(v1:in Integer, v2:in Integer) do
                        buffer((pointer+count) mod N) := v1;
                        buffer((pointer+count+1) mod N) := v2;
                        count:=count+2;
                    end Put;
            or

            -- THIS IS WHERE MY PROBLEM IS. Reading from buffer.
            -- I first need to determine what to call between ReadOne and ReadTwo

                accept GetFlag(f:out Integer) do
                    f:=flag;
                end GetFlag;

                select
                    when count > 0 =>
                        accept GetOne(v:out Integer) do
                            v:=buffer(pointer);
                            pointer := (pointer + 1) mod N;
                            count := count + 1;
                        end GetOne; 
                or
                    when count > 1 =>
                        accept GetTwo(v1:out Integer, v2:out Integer)do
                            v1:=buffer(pointer);
                            v2:=buffer((pointer+1) mod N);
                            pointer := (pointer + 2) mod N;
                            count := count + 2;  
                        end GetTwo;
                end select;
           end select;
       end loop;
   end bbuffer;
任务bbuffer是
N:常数整数:=20;
缓冲区:整数的数组(0..N-1);
指针:整数范围0..N-1;
计数:整数范围0..N;
标志:整数范围0..1;
开始
环
挑选
当计数
接受PutOne(v:整数)do
缓冲区((指针+计数)模块N):=v;
计数:=计数+1;
端置;
或
当计数
接受PutTwo(v1:整数,v2:整数)do
缓冲区((指针+计数)模块N):=v1;
缓冲区((指针+计数+1)模N):=v2;
计数:=计数+2;
端置;
或
--这就是我的问题所在。从缓冲区读取数据。
--我首先需要确定在ReadOne和ReadTwo之间调用什么
接受GetFlag(f:out整数)do
f:=旗帜;
结束标志;
选择
当计数>0=>
接受GetOne(v:out整数)do
v:=缓冲区(指针);
指针:=(指针+1)模N;
计数:=计数+1;
结束通话;
或
当计数>1=>
接受GetTwo(v1:out整数,v2:out整数)do
v1:=缓冲区(指针);
v2:=缓冲区((指针+1)模N);
指针:=(指针+2)模N;
计数:=计数+2;
结束二;
终端选择;
终端选择;
端环;
端部缓冲;
标志在A写入缓冲区时设置,在B写入缓冲区时取消设置


如果您能在这方面提供帮助,我将不胜感激,谢谢

好的,首先:在Ada中,任务必须用单独的声明和主体声明。声明声明声明了其他任务可能要调用的所有条目。正文包含任务的代码,这就是上面的代码。您的任务声明如下所示:

task bbuffer is
    entry PutOne (v: in Integer);
    entry PutTwo (v1: in Integer; v2: in Integer);
    entry GetFlag (f: out Integer);
    entry GetOne (v: out Integer);
    entry GetTwo (v1: out Integer; v2: out Integer);   
end bbuffer;
身体将从

task body bbuffer is  -- note the keyword "body"!!
    N : constant integer := 20;
    -- and so on         
另一个问题:使用分号而不是逗号来分隔条目的参数。这既适用于上面的
条目
声明,也适用于身体中出现的
接受
语句。最后,正文中PutOne和PutTwo的
accept
语句在
end
语句上的名称错误。编译器不会(嗯)接受这个

就逻辑而言:它看起来需要一些认真的反思。如果目的是让C以与A或B写入数据相同的顺序读取数据(即FIFO队列),那么您希望C确定最后一次将数据插入缓冲区的任务的语句似乎是错误的。相反,您必须设置缓冲区,以便它跟踪每个缓冲区“元素”是有一个整数(由B写入)还是有两个整数(由A写入)。我可能会使用一种记录类型:

type Buffer_Element is record
    Num_Integers : Integer range 1 .. 2;
    First_Int    : Integer;
    Second_Int   : Integer;  -- unused if Num_Integers=1  
end record;
Buffer : array (0 .. N - 1) of Buffer_Element;
请注意,这意味着缓冲区中的整数数量根据调用PutOne和PutTwo的数量而变化。我不知道这是否符合你的要求


只要能保证C在GetFlag返回后总是调用GetOne或GetWO,嵌套的
select
的排列方式看起来就可以了。否则,bbuffer可能会暂停,A和B再也不能将任何东西放入缓冲区。另外,“accept GetFlag”应该在count>0时包含
,因为我认为,如果在缓冲区为空时调用GetFlag,您希望C阻塞它。无论如何,我不想给你太多具体的建议,因为看起来整个逻辑都需要修改。

好的,首先:在Ada中,任务必须用单独的声明和主体声明。声明声明声明了其他任务可能要调用的所有条目。正文包含任务的代码,这就是上面的代码。您的任务声明如下所示:

task bbuffer is
    entry PutOne (v: in Integer);
    entry PutTwo (v1: in Integer; v2: in Integer);
    entry GetFlag (f: out Integer);
    entry GetOne (v: out Integer);
    entry GetTwo (v1: out Integer; v2: out Integer);   
end bbuffer;
身体将从

task body bbuffer is  -- note the keyword "body"!!
    N : constant integer := 20;
    -- and so on         
另一个问题:使用分号而不是逗号来分隔条目的参数。这既适用于上面的
条目
声明,也适用于身体中出现的
接受
语句。最后,正文中PutOne和PutTwo的
accept
语句在
end
语句上的名称错误。编译器不会(嗯)接受这个

就逻辑而言:它看起来需要一些认真的反思。如果目的是让C以与A或B写入数据相同的顺序读取数据(即FIFO队列),那么您希望C确定最后一次将数据插入缓冲区的任务的语句似乎是错误的。相反,您必须设置缓冲区,以便它跟踪每个缓冲区“元素”是有一个整数(由B写入)还是有两个整数(由A写入)。我可能会使用一种记录类型:

type Buffer_Element is record
    Num_Integers : Integer range 1 .. 2;
    First_Int    : Integer;
    Second_Int   : Integer;  -- unused if Num_Integers=1  
end record;
Buffer : array (0 .. N - 1) of Buffer_Element;
请注意,这意味着缓冲区中的整数数量根据调用PutOne和PutTwo的数量而变化。我不知道这是否符合你的要求

只要您能保证C在以后总是调用GetOne或getWO,那么嵌套的
select
的排列方式看起来就可以了
Buffer (N) := Element'(Single_Value => False, First => V1, Second => V2);
type Elements_In_Buffer is range 1 .. 2;
type Element_Array is array (Elements_In_Buffer range <>) of Values;
type Element (Length : Elements_In_Buffer := 1) is
   record
      Data : Element_Array (1 .. Length);
   end record;

protected Buffer is
   entry Put (A    : in     Values);
   entry Put (A, B : in     Values);
   entry Get (Item :    out Element);
end Buffer;