練習(xí)一 Scope
任何task都要在他的子任務(wù)結(jié)束后才能結(jié)束。
對(duì)于以下的程序 請(qǐng)給出輸出順序
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;
運(yùn)行結(jié)果:
分析:Ada中有兩個(gè)種類的task
- static
這一類都是直接在聲明然后使用。他的存活范圍為生成task時(shí)所在的范圍(scope)往核。 - dynamic
這一類就使用access關(guān)鍵字來(lái)表示(指針):
聲明:
type Outer_Type_Ptr is access Outer_Type;
實(shí)例化:
Dynamic_Outer_Instance : Outer_Type_Ptr := new Outer_Type;
這一類的存活范圍為其原task聲明所在的范圍箫爷,即與其在哪里被生成無(wú)關(guān)。
之所以用到了指針而不用重新聲明一個(gè)新的task聂儒,主要是考慮到了存儲(chǔ)空間的問(wèn)題虎锚。
最后,散亂分布的相同的dynamic task會(huì)被同一個(gè)task 回收衩婚,這是最有利的一點(diǎn)窜护。
練習(xí)二 Concurrent Mergesort
實(shí)現(xiàn)一個(gè)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 ## 關(guān)鍵部分
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; ##關(guān)鍵部分
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;
在以上關(guān)鍵部分非春,我用了兩個(gè)并行的task 代替了原來(lái)順序執(zhí)行的 Mergesort (F_Low), Mergesort (F_High);
因?yàn)閙ergesort的關(guān)鍵就是separation柱徙,其中的順序執(zhí)行就在于其中一組已經(jīng)排列好了,而等待下一組的排列奇昙。所以我們做的就是讓他們同時(shí)進(jìn)行护侮。
效果: