niedziela, 25 grudnia 2011

[Ada | PL] Bufor cykliczny na obiekcie chronionym

Temat:
Realizacja bufora cyklicznego w języku Ada z wykorzystaniem obiektu chronionego.

Bufor cykliczny to prosta struktura danych zrealizowana w przypadku tego programu na tablicy pięcioelementowej, gdzie dane dodawane są i pobierane zgodnie z indeksami wskaźników (w programie GetIndex i PutIndex). Obiekt chroniony zapewnia wzajemne wykluczanie dostępu do zasobów dwóch współbieżnie działających zadań (producenta i konsumenta). Modyfikowanie danych w tablicy dokonuje się za pomocą dwóch instrukcji entry wywoływanych z obu zadań w losowych chwilach czasu. Instrukcje te zapewniają nie tylko synchronizację zadań, ale także zawieszenie zadania, jeśli nie jest spełniony warunek zapisany instrukcją when. Zadanie zostaje odwieszone, gdy warunek ponownie zostanie spełniony.



1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
with Ada.Text_Io;
use Ada.Text_Io;
with Ada.Numerics.Discrete_Random;
 
 
procedure Cyclic_Buffer is
 
   type Buffer is array (Integer range <>) of Integer;
   Size : Integer:=5;
 
   subtype Wait is Integer range 0..5;
   package Draw is new Ada.Numerics.Discrete_Random(Wait);
   use Draw;
   G : Generator;
 
   protected Protected_Buffer is
      entry Add(I : in Integer);
      entry Take(I : out Integer);
   private 
      B : Buffer(1..Size);   
      Counter : Integer:=0;
      GetIndex : Integer:=1;
      PutIndex : Integer:=1;
         
 end Protected_Buffer;
   
   task Producer;
   task Consumer;
 
   protected body Protected_Buffer is
 
      entry Add(I : in Integer) when Counter < Size is
      begin
         B(PutIndex) := I;
         PutIndex := PutIndex mod Size + 1;
         Counter := Counter + 1;                   
         end Add;
 
      entry Take(I : out Integer) when Counter > 0 is
      begin
         I:=B(GetIndex);
         GetIndex := GetIndex mod Size + 1;  
         Counter := Counter - 1;      
         end Take;
   end Protected_Buffer;   
   
 
 
task body Consumer is
   Cons_Delay_Time : Integer;
begin
   loop
      Reset(G);
      Cons_Delay_Time:=Integer(Random(G));
      delay Duration(1.3*Float(Cons_Delay_Time));
      Protected_Buffer.Take(Cons_Delay_Time);
      Put_Line("Consumer : Taking "&Cons_Delay_Time'Img);
      delay 0.15;
    end loop;
end Consumer;
 
task body Producer is
   Prod_Delay_Time : Integer;
begin
   loop
      Reset(G);
      Prod_Delay_Time := Integer(Random(G));
      delay Duration(Prod_Delay_Time);
      Protected_Buffer.Add(Prod_Delay_Time);
      Put_Line("Producer : Adding "&Prod_Delay_Time'Img);
      delay 0.15;
   end loop;
end Producer;
 
begin
   null;
end Cyclic_Buffer;

Komentarze:
[11 - 14] Deklaracje generatora liczb pseudolosowych, który odpowiada za losowe czasy opóźnienia w działaniu obu zadań (od 0 do 5 sek).
[27 - 28] Uruchomienie wykonywania zadań
[55] Opóźnienie wykonywania zadania zależne od wylosowanej liczby
[56] Pobranie z bufora wartości do zmiennej lokalnej
[77] Pusta instrukcja programu - wszystkie instrukcje wykonują się w dwóch współbieżnych zadaniach

Kompilator: Ideone.com

Brak komentarzy:

Prześlij komentarz