问题
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