首页 文章

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

提问于
浏览
1

我有一个简单的问题:

我在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 回答

  • 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;
    
  • 2

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

    • 创建受保护对象 .

    • 添加一个受保护的条目 . 该条目应仅允许在每个任务完成其作业时进行调用 .

    • 从每项任务中,当他们成为一名警卫时,任何任务都不会被提供,直到每个任务都调用了这个被保护的条目 . (我在受保护单元的私有部分内用一个简单的自然计数器变量检查了这一点 . )

    • 因此当最后一个任务加入等待条目的队列时,它允许它们一个接一个地到"get through" .

    • 如果要更改多个任务使用的变量,则在条目内部,您应该在条件为"has the last task's call already been executed"的if语句中执行此操作 . 这是必需的,因为该条目一个接一个地执行任务,所以当第一个完成,并且您更改重要变量(例如关于guard语句的某些内容)时,其他任务可以无限地在队列中等待 .

    我希望我已经清楚了 . 我认为这在其他语言中被称为循环屏障 .

相关问题