问题描述
我有以下与用餐哲学家问题相关的代码。我对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
作为唯一对象。