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