poniedziałek, 26 grudnia 2011

[Ada | EN] Circular buffer using protected object

Theme
How to implement circular buffer in Ada programming language with use of protected object.

Circular buffer is a simple data structure that contains an fixed size array and two data pointers (start of valid data and the end of valid data). Protected object provides mutual exclusion of two synchronous tasks (Producer and Consumer). Data inside buffer is being modified by calling (with random delay times) one of two entries (Add, Take). Each of them contains a when statement that ensures data cohesion. If one of entries is being called and a condition associated with apropriate when statement is not fullfilled, the task is being suspended until the condition is done.

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;

Comments:
[11 - 14] Random number generator declaration. It draws consecutive delay times for both tasks.
[27 - 28] Tasks are being triggered
[55] Delay time depends on a drawn number
[56] Local variable associates now with a value from the buffer
[77] All the instructions are being evolved in tasks so null instruction is here sufficient

Compiler: Ideone.com

Brak komentarzy:

Prześlij komentarz