Ada 指定另一个包中的子程序未阻塞?

Ada 指定另一个包中的子程序未阻塞?,ada,spark-ada,Ada,Spark Ada,SPARK限制从受保护对象中调用可能阻塞的子程序 但是,我注意到,如果调用受保护对象所在包之外的任何子程序,我会收到关于可能阻塞子程序的警告 我想用外部包告诉它调用将是非阻塞的,它缺少了什么?我试着在另一个包中放一个“addone-to-argument”子程序,但它不起作用。如果我将其移动到包含受保护对象的包中,它会这样做 我缺少什么?在ADA2020中,有一个属性Non_Blocking,它明确标记了用于静态分析的Blocking/nonblocking属性,并且编译器确保事情是正确的 但是

SPARK限制从受保护对象中调用可能阻塞的子程序

但是,我注意到,如果调用受保护对象所在包之外的任何子程序,我会收到关于可能阻塞子程序的警告

我想用外部包告诉它调用将是非阻塞的,它缺少了什么?我试着在另一个包中放一个“addone-to-argument”子程序,但它不起作用。如果我将其移动到包含受保护对象的包中,它会这样做


我缺少什么?

在ADA2020中,有一个属性
Non_Blocking
,它明确标记了用于静态分析的Blocking/nonblocking属性,并且编译器确保事情是正确的

但是,如果你被困在Ada 2012中,这并没有帮助-有一些特定的东西是“潜在阻塞”的,比如进入调用和[IIRC]事物,比如
Ada.Text\u IO.Put
-SPARK的推理是,如果它是潜在阻塞的,那么你不能确保它不是非阻塞的

根据,以下是您必须注意的事项:

在受保护的操作期间,调用 可能被阻塞的操作。以下定义用于 可能会阻止操作:

  • select_语句
  • 接受声明
  • 输入调用语句
  • 延迟声明
  • 中止声明
  • 任务创建或激活
  • 对与受保护动作具有相同目标对象的受保护子程序(或外部请求)的外部调用
  • 对其主体包含潜在阻塞操作的子程序的调用

因此,如果您试图调用的子程序有
选择
接受
延迟
,或
任务
,则可能会被阻塞。

感谢@shark8提供详细的答案

我检查了我试图调用的方法的主体,因为它是一个简单的返回语句,所以没有手册中提到的任何效果

然而,我确实发现在我试图使用的包中打开
SPARK\u Mode=>on
可以解决这个问题

这里有一个MwE重现了这个问题:

-- main.adb

pragma Profile (GNAT_Extended_Ravenscar);
pragma Partition_Elaboration_Policy (Sequential);

with P1;

procedure Main is

begin
   --  Insert code here.
   null;
end Main;

-- simple.ads
package Simple is

   procedure Do_Nothing;

end Simple;

-- simple.adb 
package body Simple is

   procedure Do_Nothing is
   begin
      null;
   end Do_Nothing;


end Simple;

-- p1.ads
pragma Profile (GNAT_Extended_Ravenscar);
pragma Partition_Elaboration_Policy (Sequential);

package P1 with 
  SPARK_Mode => On 
is

   protected Protected_Object with 
     SPARK_Mode => On
   is
      procedure Do_Something;
   end Protected_Object;


end P1;

-- p1.adb 
with Simple;

package body P1 with 
  SPARK_Mode => On 
is

   protected body Protected_Object 
   with 
     SPARK_Mode => On 
   is      
      procedure Do_Something is 
      begin
         Simple.Do_Nothing;
      end Do_Something;
   end Protected_Object;


end P1;

@DeeDee--在下面发布一个MwE…我想问题是,除非你让SPARK看到被调用子程序的内部,否则它无法判断它是否阻塞