This is an assignment and I have been asked to implement a Semaphore in Ada as the description below.
However I have implemented the Semaphore.adb
and called this Semaphore in the producerconsumer_sem.adb
which I created.
I get some output which is the following.
I'm not sure if my initialization of semaphore is correct S: CountingSemaphore(1,1);
.
I don't know where I call the S.wait
and S.Signal
now i randomly called the S.wait
before Producer put item in the buffer X := I;
and the S.Signal
after the X := I;
.
Is this the correct way?
Producer-Consumer Problem The program
producerconsumer.adb
implements a non-reliable implemen- tation of the producer-consumer problem, where data is likely be lost. In the following, you will use three different communication mechanisms to achieve a reliable implementation of the producer-consumer problem.Semaphore
The Ada language does not directly provide library functions for a semaphore. However, semaphores can be implemented by means of a protected object. Create a package specification Semaphore in the file Semaphores.ads and the corresponding package body in the file
Semaphores.adb
that implements a counting semaphore. Skeletons for the package are available on the course page.Use the semaphore package for a reliable implementation of the producer- consumer problem. Modify the file
producerconsumer.adb
and save the final code asproducerconsumer_sem.adb
. In order to use the semaphore package it shall be installed in the same directory asproducerconsumer_sem.adb
. It can then be accessed by
with Semaphores;
use Semaphores;
The Output:
OutPut: 1 1 1 2 2 3 4 4 5 6 6 7 7 8 9 9 9 10 11 11 11 12 12 13 13 13 14 15 15 16 16 17 18 18 18 19 20 20 21 21 22 22 23 24 24 24 24 25 25 26 27 27 28 29 29 30 30 31 31 32 32 33 33 33 34 35 35 35 36 36 37 37 37 38 38 38 39 40 40 40
The package
package Semaphores is
protected type CountingSemaphore(Max: Natural; Initial: Natural) is
entry Wait;
entry Signal;
private
Count : Natural := Initial;
MaxCount : Natural := Max;
end CountingSemaphore;
end Semaphores;
The Semaphore I implemented semaphores.adb
.
package body Semaphores is
protected body CountingSemaphore is
entry Wait when Count > 0 is
begin
Count := Count - 1;
end Wait;
entry Signal when Count < MaxCount is
begin
Count := Count + 1;
end Signal;
end CountingSemaphore;
end Semaphores;
The producerconsumer_sem.adb
with Ada.Text_IO;
use Ada.Text_IO;
with Ada.Real_Time;
use Ada.Real_Time;
with Ada.Numerics.Discrete_Random;
with Semaphores;
use Semaphores;
procedure ProducerConsumer_sem is
X : Integer; -- Shared Variable
N : constant Integer := 40; -- Number of produced and comsumed variables
S: CountingSemaphore(1,1);
--S1: CountingSemaphore(1,1);
pragma Volatile(X); -- For a volatile object all reads and updates of
-- the object as a whole are performed directly
-- to memory (Ada Reference Manual, C.6)
--Random Delays
subtype Delay_Interval is Integer range 50..250;
package Random_Delay is new Ada.Numerics.Discrete_Random
(Delay_Interval);
use Random_Delay;
G : Generator;
task Producer;
task Consumer;
task body Producer is
Next : Time;
begin
Next := Clock;
for I in 1..N loop
-- Write to X
S.Wait;
X := I;
S.Signal;
--Next 'Release' in 50..250ms
Next := Next + Milliseconds(Random(G));
Put_Line(Integer'Image(X));
delay until Next;
end loop;
end;
task body Consumer is
Next : Time;
begin
Next := Clock;
for I in 1..N loop
-- Read from X
S.Wait;
Put_Line(Integer'Image(X));
S.Signal;
Next := Next + Milliseconds(Random(G));
delay until Next;
end loop;
end;
begin -- main task
null;
end ProducerConsumer_sem;
On macOS, with FSF GCC 7.1.0 and GNAT GPL 2017, I changed your Put_Line
s to Put
s and got pretty-much the answer you state in the question.
The question says to create Semaphore.ads
, .adb
. This will work on Windows, and may work on macOS, but won’t work on Linux, because of GNAT’s file naming convention (see the end of this; it’s a good idea to get into the habit of using lower-case file names).
If you want to ensure that only one task has access to X
at a time, I don’t think there’s much wrong with your Wait
, Signal
calls, though when I put a delay 0.1
at the beginning of Producer
, the first value output was 151619216 (because X
isn’t initialized). However! if the point is to communicate one update to X at a time (as implied by the names producer/consumer), you should
Consumer
, Wait
only (i.e. remove the Signal
)Producer
, Signal
only (i.e. remove the Wait
). Also, remove the Put
to avoid confusion!