Reputation: 315
I'm experiencing some troubles with my program.
I have a process that calls a function (Take_Job) that is supposed to remain blocked until a time (MINIMUM_WAIT) passes. If it doesn't happen that way, a message informing of this situation will appear.
for Printer_Id in Type_Printer_Id loop
select
delay MINIMUM_WAIT
Pragma_Assert (True, "");
then abort
Take_Job (Controller,
Printer_Id,
Max_Tonner,
Job,
Change_Tonner);
Pragma_Assert
(False,
"Testing of Take_Job hasn't been successful. It should have remained blocked.");
end select;
end loop;
The function Take_Job calls to an entry in a protected object:
procedure Take_Job (R : in out Controller_Type;
Printer : in Type_Printer_Id;
Siz : in Typo_Volume;
Job : out Typo_Job;
Excep_Tonner : out Boolean) is
begin
R.Take_Job(Printer, Siz, Job, Excep_Tonner);
end Take_Job;
Where "R" is the protected object.
The following code is the entry of the protected object. Actually, the "when" condition is True because I need to check some stuff with the parameters of the entry. Since Ada doesn't allow me to do that, I copy the parameters inside the protected object and call to a "delayed entry", then in the "delayed entry" I will make sure that the condition is met before proceeding.
entry Take_Job(Printer_Id: in Type_Printer_Id; Remaining: in Type_Volume; Job: out Type_Job; exceptionTonner: out Boolean)
when True is
begin
Copy_Remaining(Printer_Id) := Remaining;
requeue Take_Job_Delayed(Printer_Id);
end Take_Job;
Let's see the "delayed entry" code:
entry Take_Job_Delayed(for J in Type_Printer_Id)(Printer_Id: in Type_Printer_Id; Remaining: in Type_Volume; Job: out Type_Job; exceptionTonner: out Boolean)
when False is -- I've done this on purpose
begin
null; -- Actually, there would be a lot of code here
end Take_Job_Delayed;
Let's say that my goal is to pass the MINIMUM_WAIT and run the "Pragma_Assert(True, "")". If I put the "when" condition of Take_Job to "False", then everything works fine. Take_Job is never accepted and the Pragma_Assert will be executed. If I set it to "True" and the "when" condition of Take_Job_Delayed to "False", I don't get the same effect and the process gets blocked and neither of the Pragma_Asserts will be executed.
Why? It looks like the problem is in the "requeue" or somewhere near that, but why is this happening?
Upvotes: 4
Views: 225
Reputation: 25511
You need to do the requeue with abort
;
entry Take_Job(Printer_Id: in Type_Printer_Id;
Remaining: in Type_Volume;
Job: out Type_Job;
exceptionTonner: out Boolean)
when True is
begin
Copy_Remaining(Printer_Id) := Remaining;
requeue Take_Job_Delayed(Printer_Id) with abort;
end Take_Job;
because otherwise the opportunity to abort the entry call has been lost. There are details in ARM 9.5.4, and a more understandable explanation in Burns & Wellings, “Concurrency in Ada”.
Upvotes: 5