Dining Philosopher problem Ada- Implementing ID Dispenser

こ雲淡風輕ζ 提交于 2021-02-11 06:22:19

问题


I have the following code, related to the dining philosopher problem. I am very new to Ada so am not sure about how to implement the Id_Dispenser package.

with Ada.Text_IO;  use Ada.Text_IO;
with Id_Dispenser;
with Semaphores;   use Semaphores;

procedure Philos is

   No_of_Philos : constant Positive := 5; -- Number of philosophers
   Meditation   : constant Duration := 0.0;

   type Table_Ix is mod No_of_Philos;

   Forks : array (Table_Ix) of Binary_Semaphore (Initially_Available => True);

   package Index_Dispenser is new Id_Dispenser (Element => Table_Ix);
   use Index_Dispenser;

   task type Philo;
   task body Philo is

      Philo_Nr : Table_Ix; -- Philisopher number

   begin
      Dispenser.Draw_Id (Id => Philo_Nr);
      Put_Line ("Philosopher" & Table_Ix'Image (Philo_Nr) & " looks for forks.");
      Forks (Philo_Nr).Wait; delay Meditation; Forks (Philo_Nr + 1).Wait;
      Put_Line ("Philosopher" & Table_Ix'Image (Philo_Nr) & " eats.");
      Forks (Philo_Nr).Signal; Forks (Philo_Nr + 1).Signal;
      Put_Line ("Philosopher" & Table_Ix'Image (Philo_Nr) & " dropped forks.");
   end Philo;

   Table : array (Table_Ix) of Philo; pragma Unreferenced (Table);

begin
   null;
end Philos;

I have implemented the following semaphore, which I think should be correct

package body semaphores is
   protected body Binary_Semaphore is
      entry Wait when Count > 0 is
      begin
         Count := Count - 1;
      end Wait;
      
      entry Release when Count < 1 is 
      begin
         Count := Count + 1;
      end Signal
   end Binary_Semaphore;   
end semaphores;

What does the Id_Dispenser need?


回答1:


Looking at your code,

type Table_Ix is mod No_of_Philos;
   ...
package Index_Dispenser is new Id_Dispenser (Element => Table_Ix);

we can tell that Id_Dispenser is a generic package with a formal type named Element, and that the formal type is modular:

generic
   type Element is mod <>;
package Id_Dispenser is

This

   Philo_Nr : Table_Ix; -- Philisopher number
begin
   Dispenser.Draw_Id (Id => Philo_Nr);

tells us that Id_Dispenser has some sort of component called Dispenser with a subprogram Draw_Id with an out parameter named Id which returns an Element.

Now, since this is a concurrent program, I'm going to guess that Dispenser is a protected object:

protected Dispenser is
   procedure Draw_Id (Id : out Element);
private
   ...
end Dispenser;

The private part could simply be an array of Boolean indexed by Element,

Available : array (Element) of Boolean := (others => True);

but unfortunately you can't have an anonymous array as a component, so you need a proper type, giving

generic
   type Element is mod <>;
package Id_Dispenser is
   type Availability is array (Element) of Boolean;
   protected Dispenser is
      procedure Draw_Id (Id : out Element);
   private
      Available : Availability := (others => True);
   end Dispenser;
end Id_Dispenser;

I'm not happy that the type Availability is visible, but the package now just needs implementing (!)


We could make Availability invisible by making Id_Dispenser.Dispenser a package, with Availability and the actual PO declared in the body. But that may be getting a little too purist for Ben’s context.




回答2:


Firstly, you shouldn't really shorten identifiers, so you should have task type Philosophers... You can always use a renaming later on.

Shouldn't you model the forks and the philosophers? Each Philosopher as a task (hint array of task types).

Look at protected objects to model the forks.




回答3:


Id_dispenser needs to implement a Draw_ID method.

Since the Dispenser variable is not declared here, it must presumably be declared in Id_dispenser. This hidden declaration is not very good style, as you can see it causes confusion; I would use a qualified name to make it obvious where it came from, as Index_Dispenser.Dispenser (which can then be renamed to reduce clutter in the rest of the code).

Id_dispenser may also need to provide an object factory method to initialise the Dispenser variable at its declaration.

Or, the intent may be that Dispenser will be the only one of its type, in which case you can treat Id_dispenser as a singleton package with Dispenser as the only object.



来源:https://stackoverflow.com/questions/63498510/dining-philosopher-problem-ada-implementing-id-dispenser

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!