首页 > 解决方案 > 餐饮哲学家问题Ada-实现ID Dispenser

问题描述

我有以下代码,与哲学家就餐问题有关。我对 Ada 很陌生,所以不确定如何实现 Id_Dispenser 包。

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;

我已经实现了以下信号量,我认为应该是正确的

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;

Id_Dispenser 需要什么?

标签: ada

解决方案


看着你的代码,

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

我们可以看出这Id_Dispenser是一个具有名为 的正式类型的通用包Element,并且正式类型是模块化的:

generic
   type Element is mod <>;
package Id_Dispenser is

这个

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

告诉我们Id_Dispenser有某种组件被一个子程序调用Dispenser,该子程序Draw_Id带有一个out名为的参数Id,它返回一个Element.

现在,由于这是一个并发程序,我猜这Dispenser是一个受保护的对象:

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

Boolean私有部分可以简单地是一个由索引的数组Element

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

但不幸的是,您不能将匿名数组作为组件,因此您需要一个适当的类型,给出

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;

我不高兴该类型Availability是可见的,但是该包现在只需要实现(!)


我们可以Availability通过制作Id_Dispenser.Dispenser一个包来使其不可见,Availability并在正文中声明实际的 PO。但这对于本的语境来说可能有点过于纯粹了。


推荐阅读