首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Ada:任务数组

Ada:任务数组
EN

Stack Overflow用户
提问于 2019-03-13 19:35:34
回答 2查看 768关注 0票数 1

将索引任务链接到相应的索引保护类型的好方法是什么?

关于具体情况,请考虑以下设置:

代码语言:javascript
复制
subtype Thread_Range is Natural range 1..n;
protected type P is ... end P;
p: array(Thread_Range) of P;

对于每个p(i),我想要一个任务t(i)来监视p(i),并在它准备好时处理它。我可以很容易地在Ada工作,但火花w/Ravenscar是更高的要求。我尝试了两种方法,它们在运行时看起来很好:

  1. T一个Integer判别式,然后为每个i实例化一个T(i);,但是这会增加不太大的i的负担。
代码语言:javascript
复制
task type T(which: Integer);
t1: T(1);
t2: T(2);
...
  1. is_not_monitored函数和set_monitor过程添加到P中。创建一个没有区分的任务数组。当t(i)开始时,它会分配自己来监视它发现的第一个尚未分配监视器的p(j)
代码语言:javascript
复制
task type T;
task body T is
  which: Integer;
  available: Boolean;
begin
  for i in Thread_Range loop
    available := p(i).is_not_monitored;
    if available then
      p(i).set_monitor;
      which := i;
    end if;
  end loop;
  -- what the task does with p(i) follows
end T;
t: array(Thread_Range) of T;

我更喜欢第二个,但不太喜欢。在任何情况下,火花“证明”了潜在的数据竞赛,我可以理解为什么(虽然我不确定它实际上是由于这个)。

这就是问题所在。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-03-14 00:29:30

这不会导致蚊虫窒息。

我认为与选项2的主要区别是,Claim检查索赔是否可能,如果可能,则在一个受保护的调用中执行索赔。

但是,我不太明白如何证明T中的循环Ps (J)是在声明Ps (J)的情况下退出的。我试着在循环后加上一个断言,但没能证明。

代码语言:javascript
复制
protected type P is
   procedure Claim (Succeeded : out Boolean);
private
   Claimed : Boolean := False;
end P;

subtype Thread_Range is Integer range 1 .. 2;

Ps : array (Thread_Range) of P;

Ts : array (Thread_Range) of T;

task body T is
   Which : Integer;
begin
Claim:
   for J in Thread_Range loop
      declare
         Claimed : Boolean;
      begin
         Ps (J).Claim (Succeeded => Claimed);
         if Claimed then
            Which := J;
            exit Claim;
         end if;
      end;
   end loop Claim;

   loop  -- having a loop keeps gnatprove quiet
      delay until Ada.Real_Time.Time_Last;
   end loop;
end T;

protected body P is
   procedure Claim (Succeeded : out Boolean) is
   begin
      if not Claimed then
         Claimed := True;
         Succeeded := True;
      else
         Succeeded := False;
      end if;
   end Claim;
end P;

在与约翰进行了带外讨论之后,我们发现这个后条件可以证明:

代码语言:javascript
复制
  procedure Claim (Succeeded : out Boolean)
  with
    Post =>
      (Is_Claimed'Old or (Succeeded and Is_Claimed))
      or
      (not Succeeded and Is_Claimed);

注意,它不是P’Old.Is_Claimed,主要是因为’Old需要一个副本,而P是有限的(因为它是一个受保护的类型)。

我们还发现了几种替代配方,它们在2017年GPL中得到了证明,但在2018年CE中却没有得到证明:例如,

代码语言:javascript
复制
      (Is_Claimed
       and
       (Is_Claimed'Old xor Succeeded)
票数 1
EN

Stack Overflow用户

发布于 2019-03-17 13:11:46

我不是这方面的专家,但你似乎无法证明任务实例和受保护对象实例之间存在一对一的关系,除非您从任务实例中显式地引用了受保护对象实例。这尤其是为了证明只有一个任务会在受保护对象的条目上排队;下面代码中的Wait条目)。因此(虽然这可能不是您想要的),但我只能通过使用可以多次实例化的通用包来解决连接任务和受保护对象的问题,同时具有监视功能。这在蚊虫CE 2018年证明如下:

代码语言:javascript
复制
generic
package Generic_Worker with SPARK_Mode is   

   task T;

   protected P is
      entry Wait;
      procedure Trigger;
   private
      Triggered : Boolean := False;
   end P;

end Generic_Worker;

身体:

代码语言:javascript
复制
package body Generic_Worker with SPARK_Mode is

   task body T is      
   begin
      loop   --  Ravenscar: Tasks must not terminate.         
         P.Wait;
      end loop;
   end T;

   protected body P is

      entry Wait when Triggered is
      begin
         Triggered := False; 
         --  Do some work.
      end Wait;

      procedure Trigger is
      begin
         Triggered := True;
      end Trigger;

   end P;

end Generic_Worker;

和实例化:

代码语言:javascript
复制
with Generic_Worker;

pragma Elaborate_All (Generic_Worker);

package Workers with SPARK_Mode is

   package Worker_0 is new Generic_Worker;
   package Worker_1 is new Generic_Worker;
   package Worker_2 is new Generic_Worker;
   package Worker_3 is new Generic_Worker;
   package Worker_4 is new Generic_Worker;

end Workers;
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55149964

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档