餐饮哲学家问题Ada-实施ID分配器

问题描述

我有以下与用餐哲学家问题相关的代码。我对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需要什么?

解决方法

查看您的代码,

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的{​​{1}}参数,该参数返回一个{{1 }}。

现在,由于这是一个并发程序,所以我猜想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和实际的PO来使Availability不可见。但这对于Ben的背景而言可能会变得过于纯粹。

,

首先,您不应该真正缩短标识符,因此您应该拥有task type Philosophers...,以后可以随时使用重命名。

您不应该为叉子和哲学家建模吗?每个哲学家都作为一个任务(任务类型的提示数组)。

查看受保护的对象以对叉子进行建模。

,

Id_dispenser需要实现Draw_ID方法。

由于此处未声明Dispenser变量,因此必须在Id_dispenser中声明它。这种隐藏的声明不是很好的样式,因为您会看到它引起混乱;我会使用一个合格的名称来使它变得明显,例如Index_Dispenser.Dispenser(然后可以重命名以减少其余代码的混乱程度)。

Id_dispenser还可能需要提供一种对象工厂方法来在其声明时初始化Dispenser变量。

或者,意图是Dispenser将是其类型中的唯一类型,在这种情况下,您可以将Id_dispenser视为单例包,而将Dispenser作为唯一对象。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...