Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Semaphore in Ada

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.

  1. I'm not sure if my initialization of semaphore is correct S: CountingSemaphore(1,1);.

  2. 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 as producerconsumer_sem.adb. In order to use the semaphore package it shall be installed in the same directory as producerconsumer_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;
like image 657
Adam Avatar asked Sep 14 '17 05:09

Adam


People also ask

What is semaphore and its use?

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.

What are the two types of semaphore?

Critical Semaphores and System Semaphores.

What are semaphores in threads?

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.

Can semaphore used in distributed system?

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.


1 Answers

On macOS, with FSF GCC 7.1.0 and GNAT GPL 2017, I changed your Put_Lines to Puts 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

  • initialize the semaphore with a count of 0 (and a max of 1). This makes it a binary semaphore.
  • in Consumer, Wait only (i.e. remove the Signal)
  • in Producer, Signal only (i.e. remove the Wait). Also, remove the Put to avoid confusion!
like image 158
Simon Wright Avatar answered Nov 25 '22 20:11

Simon Wright