如何在ADA中重新初始化任务

时间:2013-05-31 17:13:45

标签: task ada restart

我有一个简单的问题:

我在ADA中同时运行了一些任务。他们一起创建了一个模拟代表一个想象国家的选举。如果出现某种情况,我想重新启动整个模拟。所以我想中止每个任务,然后重新启动它们。如何在不重新创建任务的情况下执行此操作?我确信有一个更好的方式,但我似乎无法找到它。顺便说一句,任务是在一个数组中。在此先感谢!!

with Ada.Text_IO;
use Ada.Text_IO;
with Ada.Numerics.Discrete_Random;

procedure Election is

type RandNum is new Integer range 1..100;

package RandInt is new Ada.Numerics.Discrete_Random(RandNum);
use RandInt;

task type Youngster;
task type DarkSide;

task type Guard;

NowVoting: Boolean := False;
YoungsterNum: Positive := 7;
DarkNum: Positive := 3;
G: Generator;

type PartyType is array (Positive range 1..3) of Natural;

task Place is
entry Vote(Num: in RandNum; Cheat: in Boolean);
end Place;

protected Collector is
procedure GoHome;
procedure GuardIn;
procedure GuardOut;
procedure Arrest;
function HowManyArrested return Natural;
function HowManyGuards return Natural;
function HowMany return Integer;
private
Home: Integer := 0;
Guards: Natural := 2;
Arrested: Natural := 0;
end Collector;

task body Place is
Party: PartyType := (0,0,0);
Guard1: Guard;
Guard2: Guard;
Votes: Natural := 0;
begin

Put_Line("-----------------------------------------------");
Put_Line("         A SZAVAZĂS KEZDETÉT VESZI");
Put_Line("-----------------------------------------------");
while Collector.HowMany /= YoungsterNum and Collector.HowManyArrested /= DarkNum     loop


        accept Vote(Num: in RandNum; Cheat: in Boolean) do

            NowVoting := True;

            if Num < 33 then
                Party(1) := Party(1) + 1;
            elsif Num > 33 and Num < 66 then
                Party(2) := Party(2) + 1;
            else
                Party(3) := Party(3) + 1;
            end if;

            Votes := Votes + 1;

        delay 2.0;

            Put("Ifjonctanácsok Intergalaktikus Szövetsége: ");
            Put_Line(Integer'Image(Party(1)));
            Put("ĹfelsĂ©ge Leghűbb EllenzĂ©ke: ");
            Put_Line(Integer'Image(Party(2)));
            Put("Demokratikus Ellenzék: ");
            Put_Line(Integer'Image(Party(3)));
            Put("Ă–sszesĂ­tve: ");
            Put_Line(Natural'Image(Votes));
            Put_Line("-----------------------------------------------");
            if Cheat then
                Put_Line("!!! C S A L Ă S !!!");
            end if;

            NowVoting := False;
        end;

end loop;


if (Votes-(YoungsterNum + DarkNum)) > ((YoungsterNum + DarkNum) / 20) then
    Put_Line("A szavazást meg kell ismételni!");
end if;

end Place;

task body Youngster is
Num: RandNum;
Success: Boolean := False;
Time: Natural := 0;
begin

Reset(G);
Num := Random(G);

while Success = False loop
while Time /= 6 and Success = False loop
    if NowVoting = False and (Collector.HowManyGuards = 2 
                          or Collector.HowManyGuards = 0) then
        Place.Vote(Num, False);
        Success := True;
        Collector.GoHome;
    else
        Time := Time + 1;
        delay 1.0;
    end if;

end loop;

if Success = False then
    Num := Random(G);
    Time := 0;
end if;
end loop;

end Youngster;

task body DarkSide is
Num: RandNum;
Success: Boolean := False;
Time: Natural := 0;
begin
delay 2.0;
Reset(G);

loop
    Num := Random(G);

    if Collector.HowManyGuards = 0 and Collector.HowManyArrested /= DarkNum then
        Place.Vote(Num, True);
        delay 2.0;
    else
        Collector.Arrest;
        Put_Line("!!! L E A T A R T Ă“ Z T A T Ă S !!!");
        exit;
    end if;
end loop;

end DarkSide;

protected body Collector is
procedure GoHome is
begin
    Home := Home + 1;
end GoHome;

procedure GuardOut is
begin
    Guards := Guards - 1;
end GuardOut;

procedure GuardIn is
begin
    Guards := Guards + 1;
end GuardIn;

procedure Arrest is
begin
    Arrested := Arrested + 1;
end Arrest;

function HowManyArrested return Natural is
begin
    return Arrested;
end HowManyArrested;

function HowManyGuards return Natural is
begin
    return Guards;
end HowManyGuards;

function HowMany return Integer is
begin
    return Home;
end HowMany;
end Collector;

task body Guard is
Num: RandNum;
begin
Reset(G);
while Collector.HowMany /= YoungsterNum  and Collector.HowManyArrested /= DarkNum loop
    Num := Random(G);
    if Collector.HowManyGuards = 2 then
        if Num <= 30 then
            Collector.GuardOut;
            Put_Line("(((Ĺr kiment szabályosan!)))");
            delay 10.0;
            Collector.GuardIn;
            Put_Line("(((Ĺr visszatĂ©rt!)))");
            delay 4.0;
        end if;
    else
        if Num <= 25 then
            Collector.GuardOut;
            Put_Line("(((Ĺr kiment szabálytalanul!)))");
            delay 10.0;
            Collector.GuardIn;
            Put_Line("(((Ĺr visszatĂ©rt!)))");
            delay 4.0;
        end if;
    end if;
end loop;
end Guard;

Youngsters: array (1..YoungsterNum) of Youngster;
Dark: array(1..DarkNum) of DarkSide;

begin
null;
end Election;

put_lines是匈牙利语,没关系。所以我想做的是这是真的:

if (Votes-(YoungsterNum + DarkNum)) > ((YoungsterNum + DarkNum) / 20) then

然后我希望所有这些重新开始:

Youngsters: array (1..YoungsterNum) of Youngster;
Dark: array(1..DarkNum) of DarkSide;
task Place is
entry Vote(Num: in RandNum; Cheat: in Boolean);
end Place;

当然还有两名守卫,这是不言而喻的。我希望这很清楚。

2 个答案:

答案 0 :(得分:2)

如果选举任务目前只是一项包含在任务中的选举模拟,那么多项选举可以并行进行:

-- Not compiled
task body Simulated_Elections is

begin
   Initialize_Electoral_Information;
   Determine_Candidates;
   Run_Election;
   Inaugurate;
end Simulated_Elections;

然后只需将功能放在带退出的循环中即可:

-- Still not compiled
task body Simulated_Elections is

begin
   loop
      select
         accept The_Voice_Of_The_People;
      or
         accept Tyranny_And_Dictatorship;
         exit;
      or
         terminate;
      end select;

      Initialize_Electoral_Information;
      Determine_Candidates;
      Run_Election;
      Inaugurate;
   end loop;
end Simulated_Elections;

答案 1 :(得分:2)

好吧,我发现我找到了一个解决这个问题的答案,也很优雅,可以分享。我不会在这里发布代码,只是要点:

  1. 创建受保护对象。
  2. 为其添加一个受保护的条目。该条目应该只允许在每个任务完成其工作时进行调用。
  3. 从每项任务开始,当他们准备再次开始模拟时,请调用此条目。由于有一个守卫,在每个任务都调用这个守卫的条目之前不会执行任务。 (我在受保护单元的私有部分内用一个简单的自然计数器变量检查了这一点。)
  4. 因此,当最后一个任务加入等待条目的队列时,它允许它们一个接一个地“通过”。
  5. 如果要更改多个任务使用的变量,则在条目内部应该在if语句中执行,条件为“已执行最后一个任务的调用”。这是必需的,因为条目一个接一个地提供任务,所以当第一个完成后,你改变了重要的变量(例如关于guard语句的东西),其他任务可能无限地在队列中等待。
  6. 我希望我已经清楚了。我认为这在其他语言中被称为循环屏障。