Ada 202x (40日目) - その他のprotectedの変更 =========================================== .. post:: Jan 09, 2020 :tags: ada, ada_2022 ここまで拾えていなかった変更点を駆け足で追いかけています。 アスペクト ---------- ``entry`` の本体側にも構文上アスペクトが付けられるようになりました。 ただし現時点では ``entry`` の本体側に付けられるアスペクトは規格上定義されていません。 実装依存のアスペクトを付けるための場所となります。 .. code-block:: ada 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`` にも付けられるようになりました。 .. code-block:: ada protected P2 with CPU => 1 is procedure E2; end P2; -- P2のbodyは省略 一見MutexにCPUを割り当てるような話であり意味不明ですが、その ``protected`` への呼び出しは特定CPUから行わなければならないという意味になります。 指定と異なるCPUから呼び出された場合は ``Program_Error`` になります。 これによりロックが要らなくなる等のいいことがあるらしいです。 またこの指定によりデッドロックが回避できるケースがあります。 例えば、次のように相互に呼び出し合っている2つの ``protected`` があるとします。 .. code-block:: ada 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に固定することで別々のスレッドから同時に呼ばれない保証になります。 .. code-block:: ada 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)というものがあります。 簡単に書きますと自分自身への参照を必要とする要素は遅延初期化を要求していると見做されて後回しになります。 .. code-block:: ada 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`` にも適用されるようになりました。 .. code-block:: ada 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** .. _`AI12-0169-1`: http://www.ada-auth.org/cgi-bin/cvsweb.cgi/ai12s/ai12-0169-1.txt .. _`AI12-0192-1`: http://www.ada-auth.org/cgi-bin/cvsweb.cgi/ai12s/ai12-0192-1.txt .. _`AI12-0194-1`: http://www.ada-auth.org/cgi-bin/cvsweb.cgi/ai12s/ai12-0194-1.txt .. _`AI12-0281-1`: http://www.ada-auth.org/cgi-bin/cvsweb.cgi/ai12s/ai12-0281-1.txt .. _`AI12-0323-1`: http://www.ada-auth.org/cgi-bin/cvsweb.cgi/ai12s/ai12-0323-1.txt