ada
生産者 - 消費者パターンの実装
サーチ…
前書き
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