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;
A semaphore is simply an integer variable that is shared between threads. This variable is used to solve the critical section problem and to achieve process synchronization in the multiprocessing environment. Semaphores are of two types: Binary Semaphore – This is also known as mutex lock.
Critical Semaphores and System Semaphores.
Semaphores are typically used to coordinate access to resources, with the semaphore count initialized to the number of free resources. Threads then atomically increment the count when resources are added and atomically decrement the count when resources are removed.
Semaphores provide a simple, yet powerful mechanism for synchronization among concurrent processes. Implementation and properties of semaphores, while well understood in shared memory systems, have not received sufficient attention in distributed systems.
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!If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With