ada
Mise en œuvre du modèle producteur-consommateur
Recherche…
Introduction
Une démonstration de la manière dont le modèle producteur-consommateur est mis en œuvre dans Ada.
Syntaxe
- function Scalar ' Image (Argument: Scalar'Base) retourne String;
- tâche nom_tâche;
- task TaskName est la fin des entrées;
- le corps de la tâche Task_Name est les déclarations commencent fin du code;
- entry Nom_entrée;
- accepter Nom_Entrée;
- Sortie;
Remarques
Les exemples doivent tous garantir une terminaison de tâche correcte.
Utiliser un tampon synchronisé
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;
Notez que je suis paresseux ici: il n'y a pas de fin correcte des tâches du consommateur, une fois que tous les éléments de travail sont consommés.
Modèle Producteur-Consommateur utilisant le mécanisme Ada Rendezvous
Une solution synchrone producteur-consommateur garantit que le consommateur lit chaque donnée écrite par le producteur exactement une fois. Les solutions asynchrones permettent au consommateur d’échantillonner la sortie du producteur. Soit le consommateur consomme les données plus rapidement qu'il n'est produit, soit le consommateur consomme les données plus lentement qu'il n'est produit. L'échantillonnage permet au consommateur de gérer les données actuellement disponibles. Ces données peuvent n'être qu'un échantillonnage des données produites ou des données déjà consommées.
------------------------------------------------------------------
-- 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;
Producteur-Consommateur avec un consommateur échantillonneur
Cet exemple utilise la procédure principale comme tâche du producteur. Dans Ada, la procédure principale s'exécute toujours dans une tâche distincte de toutes les autres tâches du programme, voir exemple minimal .
------------------------------------------------------------------
-- 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;
Plusieurs producteurs et consommateurs partageant le même tampon
Cet exemple montre plusieurs producteurs et consommateurs partageant le même tampon. Les entrées protégées dans Ada implémentent une file d'attente pour gérer les tâches en attente. La politique de mise en file d'attente par défaut est 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;