Ada 202x (40日目) - その他のprotectedの変更¶
ここまで拾えていなかった変更点を駆け足で追いかけています。
アスペクト¶
entry
の本体側にも構文上アスペクトが付けられるようになりました。
ただし現時点では entry
の本体側に付けられるアスペクトは規格上定義されていません。
実装依存のアスペクトを付けるための場所となります。
protected P1 is
entry E1;
end P1;
protected P1 is
entry E1 with IMPLEMENTATION_DEFINED_ASPECT is
begin
null;
end E1;
end P1;
CPUアスペクト¶
CPU
アスペクトは task
を実行するためのCPUを固定するためのものです。
System.Multiprocessors.CPU
の範囲内(有効範囲は実装依存)の値を指定します。
その CPU
アスペクトが protected
にも付けられるようになりました。
protected P2 with CPU => 1 is
procedure E2;
end P2;
-- P2のbodyは省略
一見MutexにCPUを割り当てるような話であり意味不明ですが、その protected
への呼び出しは特定CPUから行わなければならないという意味になります。
指定と異なるCPUから呼び出された場合は Program_Error
になります。
これによりロックが要らなくなる等のいいことがあるらしいです。
またこの指定によりデッドロックが回避できるケースがあります。
例えば、次のように相互に呼び出し合っている2つの protected
があるとします。
protected P3 is
procedure Enter;
procedure Sync;
end P3;
protected P4 is
procedure Enter;
procedure Sync;
end P4;
protected body P3 is
procedure Enter is
begin
P4.Sync;
end Enter;
procedure Sync is
begin
null;
end Sync;
end P3;
protected body P4 is
procedure Enter is
begin
P3.Sync;
end Enter;
procedure Sync is
begin
null;
end Sync;
end P4;
P3.Enter
と P4.Enter
が別々のスレッドから同時に呼ばれますと、それぞれロックがかかった状態で更にお互いのロックを獲得しようとしますからデッドロックします。
しかし P3.Enter
と P4.Enter
が同時に呼ばれなければデッドロックしません。
CPU
アスペクトでこれらの protected
を同じCPUに固定することで別々のスレッドから同時に呼ばれない保証になります。
protected P3 with CPU => 1 is
procedure Enter;
procedure Sync;
end P3;
protected P4 with CPU => 1 is
procedure Enter;
procedure Sync;
end P4;
遅延初期化の要求¶
オブジェクトの初期化に関係するルールの中には遅延初期化の要求(require late initialization)というものがあります。 簡単に書きますと自分自身への参照を必要とする要素は遅延初期化を要求していると見做されて後回しになります。
declare
type T;
function Get_Early (Object : T) return Integer;
type T is
record
Late : Integer := Get_Early (T);
Early : Integer := 1;
end record;
function Get_Early (Object : T) return Integer is (Object.Early);
Object_1 : T;
Object_2 : T := (Early => 2, others => <>);
ここで要素 Late
と Early
の初期化順を考えます。
ソースコードの登場順では Late
の方が先ですが Late
のデフォルト初期化の式では関数経由で Early
を参照しています。
ですので Early
を先に初期化して欲しいわけです。
Late
は与えられた式の中で自分自身を参照していますので遅延初期化を要求していると見做され望ましい順番で初期化されます。
このルールが protected
にも適用されるようになりました。
protected P5 is
private
function Get_Early return Integer;
Late : Integer := Get_Early;
Early : Integer := 1;
end P5;
protected body P5 is
function Get_Early return Integer is
begin
return Early;
end Get_Early;
end P5;
この Get_Early
の内部呼び出しではオブジェクト名から .
で続けていませんが P5
自身を参照しています。
そのため遅延初期化を要求していると見做されるようになりました。
関連AI¶
AI12-0169-1 Aspect specifications for entry bodies
AI12-0192-1 "requires late initialization" and protected types
AI12-0194-1 Language-defined aspects and entry bodies
AI12-0281-1 CPU Affinity for Protected Objects
AI12-0323-1 Implementation Advice for the CPU aspect for protected types