Ada 202x (24日目) - 'Index

休憩。 今までで一番短いです。

経緯

task/protected のマイナーな機能に複数 entry をインデックスで区別するというものがあります。 ひとつの呼び出しがインデックス値によって各エントリに振り分けられます。

declare
   task T is
      entry Dispatch (Integer range 1 .. 3) (Parameter : in String);
   end T;
   task body T is
   begin
      accept Dispatch (1) (Parameter : in String) do
         requeue Dispatch (2); -- たらい回し
      end Dispatch;
      accept Dispatch (2) (Parameter : in String) do
         requeue Dispatch (3); -- 再びたらい回し
      end Dispatch;
      accept Dispatch (3) (Parameter : in String) do
         Ada.Text_IO.Put_Line (Parameter);
      end Dispatch;
   end T;
begin
   T.Dispatch (1) ("MESSAGE");

このインデックス値には名前が付いていません。 accept文の側は分かれていますのでAda 2005までは何も困らなかったのですが、Ada 2012からの事前条件/事後条件は仕様部側に書くことになります。 そのため実際に呼ばれているエントリの区別をつけることができませんでした。

Ada 202xでの改善

'Index

インデックス値を entry'Index 属性として参照できるようになりました。

declare
   use type Ada.Task_Identification.Task_Id;
   task T is
      entry Dispatch (Integer range 1 .. 3) (Parameter : in String)
        with Pre =>
          Dispatch'Index = 1
            or else Ada.Task_Identification.Current_Task = T'Identity;
   end T;
   -- 以下省略

この例では T は最初に 1 を待ちますのでいきなり 23 が呼ばれますとデッドロックします。 そのため外から呼ばれるときは 1 でなければならない、という事前条件を付けました。

pygmentsってテキトーですよね、と改めてしみじみと。

関連AI

  • AI12-0143-1 Using an entry index of a family in a precondition

  • AI12-0193-1 Postcondition failure for a task entry

所感

インデックス値付きのエントリは忘れられているぐらいマイナーという話でした。 synchronized interface でも使えませんし。