Отмена процесса в Аде, который использует защищенный объект, который требует

У меня проблемы с моей программой.

У меня есть процесс, который вызывает функцию (Take_Job), которая должна оставаться заблокированной, пока не пройдет время (MINIMUM_WAIT). Если этого не произойдет, появится сообщение об этой ситуации.

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;

Функция Take_Job вызывает запись в защищенном объекте:

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;

Где "R" - защищенный объект.

Следующий код представляет собой запись защищенного объекта. На самом деле условие "когда" истинно, потому что мне нужно проверить кое-что с параметрами записи. Поскольку Ада не позволяет мне этого делать, я копирую параметры внутри защищенного объекта и вызываю "отложенную запись", а затем в "отложенной записи" я проверю, что условие выполнено, прежде чем продолжить.

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;

Давайте посмотрим код "отложенной записи":

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;

Допустим, моя цель - передать MINIMUM_WAIT и запустить "Pragma_Assert(True, "")". Если я поставлю условие "когда" Take_Job в "False", то все будет работать нормально. Take_Job никогда не принимается, и Pragma_Assert будет выполнен. Если я установлю его в "True" и условие "когда" Take_Job_Delayed в "False", я не получу тот же эффект, и процесс будет заблокирован, и ни один из Pragma_Asserts не будет выполнен.

Зачем? Похоже, что проблема в "требовании" или где-то рядом, но почему это происходит?

1 ответ

Решение

Вы должны сделать заявку 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;

потому что в противном случае возможность прервать входной вызов была потеряна. Подробности в ARM 9.5.4 и более понятное объяснение в Burns & Wellings "Параллельность в Аде".

Другие вопросы по тегам