是否有必要将共享数组数据包装为受保护的类型?

时间:2018-10-11 06:06:19

标签: ada

我知道这通常是不好的做法(ARM可能会说这是未定义的行为),但是我试图编写一个包含许多浮点数的快速文本解析器,并且包装已加载的代码将非常昂贵假定将数据逐个字符地检查,并且可以在堆栈中传递多达一百万个浮点数或通过切片,则将文本转换为受保护的类型。

在Ada(GNAT)中,如果该阵列从未被写入且只能被读取,是否可以“安全地”划分不受保护的阵列以供多个任务使用?

如:

 Text : array (1..1_000_000) of Character := ...
 begin
   Task_1.Initialize (Start_Index => 1, End_Index => 10_000);
   Task_2.Initialize (Start_Index => 10_001, End_Index => 20_000);
 ...

1 个答案:

答案 0 :(得分:4)

是的。这是安全的,因为没有与读取数据相关的竞争条件,并且没有时间重叠的写入操作。 例如,以下代码使用这种技术对整数数组执行并行加法运算。

package Parallel_Addition is
   type Data_Array is array(Integer range <>) of Integer;
   type Data_Access is access all Data_Array;
   function Sum(Item : in not null Data_Access) return Integer;
end Parallel_Addition;

package body Parallel_Addition is

   ---------
   -- Sum --
   ---------

   function Sum (Item : in not null Data_Access) return Integer is
      task type Adder is
         entry Set (Min : Integer; Max : Integer);
         entry Report (Value : out Integer);
      end Adder;

      task body Adder is
         Total : Integer := 0;
         First : Integer;
         Last  : Integer;
      begin
         accept Set (Min : Integer; Max : Integer) do
            First := Min;
            Last  := Max;
         end Set;
         for I in First .. Last loop
            Total := Total + Item (I);
         end loop;
         accept Report (Value : out Integer) do
            Value := Total;
         end Report;
      end Adder;
      A1  : Adder;
      A2  : Adder;
      R1  : Integer;
      R2  : Integer;
      Mid : constant Integer := (Item'Length / 2) + Item'First;
   begin
      A1.Set (Min => Item'First, Max => Mid);
      A2.Set (Min => Mid + 1, Max => Item'Last);
      A1.Report (R1);
      A2.Report (R2);
      return R1 + R2;
   end Sum;

end Parallel_Addition;

with Parallel_Addition; use Parallel_Addition;
with Ada.Text_IO;       use Ada.Text_IO;
with Ada.Calendar;      use Ada.Calendar;

procedure Parallel_Addition_Test is
   The_Data : Data_Access := new Data_Array (1 .. Integer'Last / 5);
   Start    : Time;
   Stop     : Time;
   The_Sum  : Integer;

begin
   The_Data.all := (others => 1);
   Start        := Clock;
   The_Sum      := Sum (The_Data);
   Stop         := Clock;
   Put_Line ("The sum is: " & Integer'Image (The_Sum));
   Put_Line
     ("Addition elapsed time is " &
      Duration'Image (Stop - Start) &
        " seconds.");
   Put_Line
     ("Time per addition operation is " &
        Float'Image(Float(Stop - Start) / Float(The_Data'Length)) &
        " seconds.");
end Parallel_Addition_Test;