将索引任务链接到相应的索引保护类型的好方法是什么?
关于具体情况,请考虑以下设置:
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是更高的要求。我尝试了两种方法,它们在运行时看起来很好:
T一个Integer判别式,然后为每个i实例化一个T(i);,但是这会增加不太大的i的负担。task type T(which: Integer);
t1: T(1);
t2: T(2);
...is_not_monitored函数和set_monitor过程添加到P中。创建一个没有区分的任务数组。当t(i)开始时,它会分配自己来监视它发现的第一个尚未分配监视器的p(j)。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;我更喜欢第二个,但不太喜欢。在任何情况下,火花“证明”了潜在的数据竞赛,我可以理解为什么(虽然我不确定它实际上是由于这个)。
这就是问题所在。
发布于 2019-03-14 00:29:30
这不会导致蚊虫窒息。
我认为与选项2的主要区别是,Claim检查索赔是否可能,如果可能,则在一个受保护的调用中执行索赔。
但是,我不太明白如何证明T中的循环Ps (J)是在声明Ps (J)的情况下退出的。我试着在循环后加上一个断言,但没能证明。
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;在与约翰进行了带外讨论之后,我们发现这个后条件可以证明:
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中却没有得到证明:例如,
(Is_Claimed
and
(Is_Claimed'Old xor Succeeded)发布于 2019-03-17 13:11:46
我不是这方面的专家,但你似乎无法证明任务实例和受保护对象实例之间存在一对一的关系,除非您从任务实例中显式地引用了受保护对象实例。这尤其是为了证明只有一个任务会在受保护对象的条目上排队;下面代码中的Wait条目)。因此(虽然这可能不是您想要的),但我只能通过使用可以多次实例化的通用包来解决连接任务和受保护对象的问题,同时具有监视功能。这在蚊虫CE 2018年证明如下:
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;身体:
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;和实例化:
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;https://stackoverflow.com/questions/55149964
复制相似问题