代码 (Ada)4. TASK LIFE SPANS

练习一 Scope

任何task都要在他的子任务结束后才能结束。
对于以下的程序 请给出输出顺序

with Ada.Calendar;      use Ada.Calendar;
with Ada.Float_Text_IO; use Ada.Float_Text_IO;
with Ada.Text_IO;       use Ada.Text_IO;

procedure Task_Scopes is

   Start_Up_Time : constant Time := Clock;

   procedure Put_Line_Time (S : String) is

   begin
      -- Prefixes the time since startup as seconds with two decimal places
      Put (Float (Clock - Start_Up_Time), 1, 2, 0); Put_Line (" seconds: " & S);
   end Put_Line_Time;

   task type Outer_Type;
   type Outer_Type_Ptr is access Outer_Type;
   task body Outer_Type is

   begin
      delay 0.6; Put_Line_Time ("-- End of an outer task");
   end Outer_Type;

   task Static_Outer_Task;
   task body Static_Outer_Task is

   begin
      delay 0.1; Put_Line_Time ("Start of Static_Outer_Task");
      declare

         task type Inner_Type;
         type Inner_Type_Ptr is access Inner_Type;
         task body Inner_Type is

         begin
            delay 0.6; Put_Line_Time ("-- End of an inner task");
         end Inner_Type;

         task Static_Inner_Task;
         task body Static_Inner_Task is

         begin
            delay 0.2; Put_Line_Time ("Start of Static_Inner_Task");
            declare
               Inner_Task_Instance : Inner_Type;
               Outer_Task_Instance : Outer_Type;
               Dynamic_Inner_Instance : Inner_Type_Ptr := new Inner_Type;
--                 Dynamic_Outer_Instance : Outer_Type_Ptr := new Outer_Type;
            begin
               delay 0.3; Put_Line_Time ("End of Static_Inner_Task declare block");
            end;
            delay 0.1; Put_Line_Time ("End of Static_Inner_Task");
         end Static_Inner_Task;

      begin
         delay 0.4; Put_Line_Time ("End of Static_Outer_Task declare block");
      end;
      delay 0.1; Put_Line_Time ("End of Static_Outer_Task");
   end Static_Outer_Task;

begin
   delay 0.2; Put_Line_Time ("Start of main scope");
   delay 0.2; Put_Line_Time ("End of main scope");
end Task_Scopes;

运行结果:

代码 (Ada)4. TASK LIFE SPANS_第1张图片

分析:Ada中有两个种类的task

  1. static
    这一类都是直接在声明然后使用。他的存活范围为生成task时所在的范围(scope)。
  2. dynamic
    这一类就使用access关键字来表示(指针):

声明:

type Outer_Type_Ptr is access Outer_Type;

实例化:

Dynamic_Outer_Instance : Outer_Type_Ptr := new Outer_Type;

这一类的存活范围为其原task声明所在的范围,即与其在哪里被生成无关。
之所以用到了指针而不用重新声明一个新的task,主要是考虑到了存储空间的问题。

最后,散乱分布的相同的dynamic task会被同一个task 回收,这是最有利的一点。

练习二 Concurrent Mergesort

实现一个concurrent mergesort。

with Ada.Exceptions; use Ada.Exceptions;
with Ada.Text_IO;    use Ada.Text_IO;
with CPU_Counter;    use CPU_Counter;

procedure Concurrent_Mergesort (Sort_Field : in out Element_Array) is

   procedure Mergesort (F : in out Element_Array) is

   begin
      if F'Length > 1 then
         declare
            Middle : constant Index := Index'Val (Index'Pos (F'First) + F'Length / 2);

            subtype Low_Range  is Index range F'First .. Index'Pred (Middle);
            subtype High_Range is Index range Middle  .. F'Last;

            F_Low  : aliased Element_Array := F (Low_Range);
            F_High : aliased Element_Array := F (High_Range);

            Gained_Agent : Boolean := False;
                    
         begin
            if CPUs_Potentially_Available then
               CPU_Count.Try_Check_One_Out (Gained_Agent);
            end if;

            if Gained_Agent then   ## 关键部分
               declare
                  task sort_L;
                  
                  task body sort_L is 
                  begin                      
                     Mergesort (F_Low);
                  end;
                  
                  task  sort_H;           
                  
                  task body sort_H is 
                  begin
                     Mergesort (F_High);
                  end;
                  
               begin
                  null;
               end;                ##关键部分
               
            else
               Mergesort (F_Low);
               Mergesort (F_High);
            end if;

            declare
               Low          : Low_Range  := Low_Range'First;
               High         : High_Range := High_Range'First;
               Low_Element  : Element    := F_Low  (Low);
               High_Element : Element    := F_High (High);

            begin
               Merge : for i in F'Range loop

                  if Low_Element < High_Element then
                     F (i) := Low_Element;
                     if Low = F_Low'Last then
                        F (Index'Succ (i) .. F'Last) := F_High (High .. F_High'Last);
                        exit Merge;
                     else
                        Low  := Index'Succ (Low); Low_Element  := F_Low (Low);
                     end if;
                  else
                     F (i) := High_Element;
                     if High = F_High'Last then
                        F (Index'Succ (i) .. F'Last) := F_Low (Low .. F_Low'Last);
                        exit Merge;
                     else
                        High := Index'Succ (High); High_Element := F_High (High);
                     end if;
                  end if;
               end loop Merge;
            end;
         end;
      end if;
   end Mergesort;

begin
   Mergesort (Sort_Field);
end Concurrent_Mergesort;

在以上关键部分,我用了两个并行的task 代替了原来顺序执行的 Mergesort (F_Low), Mergesort (F_High);
因为mergesort的关键就是separation,其中的顺序执行就在于其中一组已经排列好了,而等待下一组的排列。所以我们做的就是让他们同时进行。

效果:

代码 (Ada)4. TASK LIFE SPANS_第2张图片

你可能感兴趣的:(代码 (Ada)4. TASK LIFE SPANS)