サーチ…


前書き

Adaでプロデューサ - コンシューマパターンがどのように実装されているかのデモンストレーション。

構文

  • 関数スカラ画像 (引数:Scalar'Base)は文字列を返します。
  • タスク Task_Name;
  • タスク Task_Nameはエントリの終わりです。
  • タスク本体Task_NameはDeclarations beginコード終了です。
  • エントリEntry_Name;
  • Entry_Nameを受け入れます。
  • 出口;

備考

これらの例は、すべて適切なタスクの終了を保証する必要があります。

同期バッファの使用

with Ada.Containers.Synchronized_Queue_Interfaces;
with Ada.Containers.Unbounded_Synchronized_Queues;
with Ada.Text_IO;

procedure Producer_Consumer_V1 is
   type Work_Item is range 1 .. 100;

   package Work_Item_Queue_Interfaces is
     new Ada.Containers.Synchronized_Queue_Interfaces
           (Element_Type => Work_Item);

   package Work_Item_Queues is
     new Ada.Containers.Unbounded_Synchronized_Queues
           (Queue_Interfaces => Work_Item_Queue_Interfaces);

   Queue : Work_Item_Queues.Queue;

   task type Producer;
   task type Consumer;

   Producers : array (1 .. 1)  of Producer;
   Consumers : array (1 .. 10) of Consumer;

   task body Producer is
   begin
      for Item in Work_Item loop
         Queue.Enqueue (New_Item => Item);
      end loop;
   end Producer;

   task body Consumer is
      Item : Work_Item;
   begin
      loop
         Queue.Dequeue (Element => Item);
         Ada.Text_IO.Put_Line (Work_Item'Image (Item));
      end loop;
   end Consumer;

begin
   null;
end Producer_Consumer_V1;

私はここで怠けていることに注意してください:すべての作業項目が消費されたら、消費者タスクの適切な終了はありません。

Ada Rendezvousメカニズムを用いたプロデューサー - 消費者パターン

同期プロデューサ - コンシューマソリューションは、コンシューマがプロデューサによって書き込まれたすべてのデータ項目を正確に読み取ることを保証します。非同期ソリューションは、消費者がプロデューサの出力をサンプリングすることを可能にする。消費者がデータを消費するよりも速く消費するか、または消費者がデータを消費するよりも遅く消費する。サンプリングは、消費者が現在利用可能なデータを処理することを可能にする。そのデータは、生成されたデータのサンプリングのみであってもよく、既に消費されたデータであってもよい。

------------------------------------------------------------------
-- synchronous PC using Rendezvous --
------------------------------------------------------------------
with Ada.Text_IO; use Ada.Text_IO;

procedure PC_Rendezvous is
   task Producer;
   task Consumer is
      entry Buf(Item : in Integer);
   end Consumer;
   task body Producer is
   begin
      for I in 1..10 loop
         Put_Line("Producer writing" & Integer'Image(I));
         Consumer.Buf(I);
      end loop;
   end Producer;
   task body Consumer is
      Temp : Integer;
   begin
      loop
         select
            accept Buf(Item : in Integer) do
               temp := Item;
            end;
            Put_Line("Consumer read" & Integer'Image(Temp));
         or
            terminate;
         end select;
      end loop;
   end Consumer;

begin
   null;
end PC_Rendezvous;

プロデューサー - 消費者をサンプリングする消費者

この例では、メインプロシージャをプロデューサタスクとして使用します。 Adaでは、メインプロシージャは常にプログラム内の他のすべてのタスクとは別のタスクで実行されます。 最小限の例を参照してください

------------------------------------------------------------------
-- Sampling Consumer --
------------------------------------------------------------------
with Ada.Text_IO; use Ada.Text_IO;

procedure Sampling_PC is
   protected Buf is
      procedure Write(Item : in Integer);
      function Read return Integer;
      procedure Set_Done;
      function Get_Done return Boolean;
   private
      Value : Integer := Integer'First;
      Is_Done : Boolean := False;
   end Buf;
   protected body Buf is
      procedure Write(Item : in Integer) is
      begin
         Value := Item;
      end Write;
      function Read return Integer is
      begin
         return Value;
      end Read;
      procedure Set_Done is
      begin
         Is_Done := True;
      end Set_Done;
      function Get_Done return Boolean is
      begin
         return Is_Done;
      end Get_Done;
   end Buf;

   task Consumer;
   task body Consumer is
   begin
      while not Buf.Get_Done loop
          Put_Line("Consumer read" & Integer'Image(Buf.Read));
      end loop;
   end Consumer;

begin
   for I in 1..10 loop
     Put_Line("Producer writing" & Integer'Image(I));
     Buf.Write(I);
   end loop;
   Buf.Set_Done;
end Sampling_PC;

同じバッファを共有する複数のプロデューサとコンシューマ

この例では、複数のプロデューサとコンシューマが同じバッファを共有しています。 Adaの保護されたエントリは、待機中のタスクを処理するキューを実装します。デフォルトのキューイングポリシーはFirst In First Outです。

------------------------------------------------------------------
-- Multiple producers and consumers sharing the same buffer --
------------------------------------------------------------------
with Ada.Text_IO; use Ada.Text_Io;

procedure N_Prod_Con is
   protected Buffer is
      Entry Write(Item : in Integer);
      Entry Read(Item : Out Integer);
   private
      Value  : Integer := Integer'Last;
      Is_New : Boolean := False;
   end Buffer;
   protected body Buffer is
      Entry Write(Item : in Integer) when not Is_New is
      begin
         Value := Item;
         Is_New := True;
      end Write;
      Entry Read(Item : out Integer) when Is_New is
      begin
         Item := Value;
         Is_New := False;
      end Read;
   end Buffer;

   task type Producers(Id : Positive) is
      Entry Stop;
   end Producers;
   task body Producers is
      Num : Positive := 1;
   begin
      loop
         select
            accept Stop;
            exit;
         or
            delay 0.0001;
         end select;
         Put_Line("Producer" & Integer'Image(Id) & " writing" & Integer'Image(Num));
         Buffer.Write(Num);
         Num := Num + 1;
      end loop;
   end Producers;

   task type Consumers(Id : Positive) is
      Entry Stop;
   end Consumers;

   task body Consumers is
      Num : Integer;
   begin
      loop
         select
            accept stop;
            exit;
         or
            delay 0.0001;
         end select;
         Buffer.Read(Num);
         Put_Line("Consumer" & Integer'Image(ID) & " read" & Integer'Image(Num));
      end loop;
   end Consumers;
   P1 : Producers(1);
   P2 : Producers(2);
   P3 : Producers(3);
   C1 : Consumers(1);
   C2 : Consumers(2);
   C3 : Consumers(3);
begin
   delay 0.2;
   P1.Stop;
   P2.Stop;
   P3.Stop;
   C1.Stop;
   C2.Stop;
   C3.Stop;
end N_Prod_Con;


Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow