Справочник по Ada 2005
9.6 Операторы задержки, продолжительность и время
Оператор delay_statement используется для приостановки дальнейшего выполнения до достижения указанного времени окончания. Время окончания можно указать либо как конкретную точку во времени (в операторе delay_until_statement), либо в секундах от текущего времени (в операторе delay_relative_statement). Встроенный пакет Calendar предоставляет определения для типа Time и связанных операций, включая функцию Clock, возвращающую текущее время.
Синтаксис
Правила разрешения имен
Ожидаемый тип для delay_expression в операторе delay_relative_statement — предопределённый тип Duration. Ожидаемый тип для delay_expression в операторе delay_until_statement — любой нелимитированный тип.
Правила допустимости
Может быть несколько временных баз, каждая с соответствующим таймером и соответствующим типом времени. Тип delay_expression в операторе delay_until_statement должен быть типом времени — либо типом Time, определённым во встроенном пакете Calendar (см. ниже), либо каким-то другим типом времени, определённым реализацией (см. D.8).
Статическая семантика
Существует предопределённый фиксированный тип Duration, объявленный во видимой части пакета Standard. Значение типа Duration используется для представления длительности временного интервала, выраженной в секундах. Тип Duration не зависит от конкретной временной базы, но может быть использован с любой временной базой.
Значение типа Time в пакете Calendar, или какого-либо другого, определённого реализацией типа времени, представляет время, как показано соответствующим таймером.
Существует следующий встроенный библиотечный пакет:
package Ada.Calendar is
type Time is private;
subtype Year_Number is Integer range 1901 .. 2399;
subtype Month_Number is Integer range 1 .. 12;
subtype Day_Number is Integer range 1 .. 31;
subtype Day_Duration is Duration range 0.0 .. 86_400.0;
subtype Month_Number is Integer range 1 .. 12;
subtype Day_Number is Integer range 1 .. 31;
subtype Day_Duration is Duration range 0.0 .. 86_400.0;
function Clock return Time;
function Year (Date : Time) return Year_Number;
function Month (Date : Time) return Month_Number;
function Day (Date : Time) return Day_Number;
function Seconds(Date : Time) return Day_Duration;
function Month (Date : Time) return Month_Number;
function Day (Date : Time) return Day_Number;
function Seconds(Date : Time) return Day_Duration;
procedure Split (Date : in Time;
Year : out Year_Number;
Month : out Month_Number;
Day : out Day_Number;
Seconds : out Day_Duration);
Year : out Year_Number;
Month : out Month_Number;
Day : out Day_Number;
Seconds : out Day_Duration);
function Time_Of(Year : Year_Number;
Month : Month_Number;
Day : Day_Number;
Seconds : Day_Duration := 0.0)
return Time;
Month : Month_Number;
Day : Day_Number;
Seconds : Day_Duration := 0.0)
return Time;
function "+" (Left : Time; Right : Duration) return Time;
function "+" (Left : Duration; Right : Time) return Time;
function "-" (Left : Time; Right : Duration) return Time;
function "-" (Left : Time; Right : Time) return Duration;
function "+" (Left : Duration; Right : Time) return Time;
function "-" (Left : Time; Right : Duration) return Time;
function "-" (Left : Time; Right : Time) return Duration;
function "<" (Left, Right : Time) return Boolean;
function "<="(Left, Right : Time) return Boolean;
function ">" (Left, Right : Time) return Boolean;
function ">="(Left, Right : Time) return Boolean;
function "<="(Left, Right : Time) return Boolean;
function ">" (Left, Right : Time) return Boolean;
function ">="(Left, Right : Time) return Boolean;
Time_Error : exception;
private
... -- не задано языком
end Ada.Calendar;
... -- не задано языком
end Ada.Calendar;
Динамическая семантика
Для выполнения оператора delay_statement, сначала вычисляется delay_expression. Для оператора delay_until_statement, временем окончания задержки является значение delay_expression во временной базе, связанной с типом expression. Для оператора delay_relative_statement, время окончания определяется как текущее время во временной базе, связанной с относительными задержками, плюс значение delay_expression, преобразованное к типу Duration, а затем округлённое вверх до ближайшего момента времени срабатывания таймера. Временная база, связанная с относительными задержками, определяется в D.9, «Точность задержки», или определена реализацией.
Задача, выполняющая оператор delay_statement, блокируется до достижения времени окончания, после чего становится готовой к выполнению. Если время окончания уже прошло, задача не блокируется.
Если производится попытка отмены оператора delay_statement (в рамках оператора asynchronous_select или прерывания — см. 9.7.4 и 9.8), оператор отменяется, если время окончания ещё не наступило, тем самым завершая оператор delay_statement.
Временная база, связанная с типом Time пакета Calendar, определяется реализацией. Функция Clock пакета Calendar возвращает значение, представляющее текущее время для этой временной базы. Значение именованной константы System.Tick (см. 13.7) приближённо соответствует длительности реального интервала времени, в течение которого значение Calendar.Clock остаётся постоянным.
Функции Year, Month, Day и Seconds возвращают соответствующие значения для данного значения типа Time, в соответствии с определённой реализацией часового пояса; процедура Split возвращает все четыре соответствующих значения. Обратно, функция Time_Of объединяет номер года, номер месяца, номер дня и длительность в значение типа Time. Операторы "+" и "–" для сложения и вычитания времени и длительности, а также реляционные операторы для времени, имеют обычный смысл.
Если Time_Of вызывается со значением seconds 86_400.0, возвращаемое значение равно значению Time_Of для следующего дня со значением seconds 0.0. Возвращаемое функцией Seconds или через параметр Seconds процедуры Split значение всегда меньше 86_400.0.
Исключение Time_Error генерируется функцией Time_Of, если фактические параметры не образуют корректной даты. Это исключение также генерируется операторами "+" и "–", если результат не представим в типе Time или Duration, соответственно. Это исключение также генерируется функциями Year, Month, Day и Seconds и процедурой Split, если номер года заданной даты находится за пределами диапазона подтипа Year_Number.
Требования к реализации
Реализация типа Duration должна допускать представление временных интервалов (как положительных, так и отрицательных) до по крайней мере 86400 секунд (один день); Duration'Small не должен быть больше двадцати миллисекунд. Реализация типа Time должна допускать представление всех дат с номерами года в диапазоне Year_Number; она может также допускать представление других дат (как более ранних, так и более поздних).
Разрешения для реализации
Реализация может определять дополнительные типы времени (см. D.8).
Реализация может сгенерировать Time_Error, если значение delay_expression в операторе delay_until_statement оператора select_statement представляет время, которое больше, чем на 90 дней от текущего времени. Фактический предел, если таковой имеется, определяется реализацией.
Рекомендации для реализации
Всякий раз, когда это возможно в реализации, значение Duration'Small должно быть не больше 100 микросекунд.
Временная база для операторов delay_relative_statement должна быть монотонной; она не обязательно должна быть той же временной базой, что используется для Calendar.Clock.
ПРИМЕЧАНИЯ
32 Оператор delay_relative_statement с отрицательным значением delay_expression эквивалентен оператору с нулевым значением.
END_OF_DOCUMENT_MARKER
33 Задачу окружения может выполнить delay_statement; следовательно, delay_statement могут выполняться в рамках разработки library_item или выполнения основной подпрограммы. Такие операторы приостанавливают задачу окружения (см. 10.2).
34 delay_statement является точкой завершения прерывания и потенциально блокирующей операцией, даже если задача фактически не заблокирована.
35 Нет необходимой связи между System.Tick (разрешением часов пакета Calendar) и Duration'Small (small типа Duration).
Примеры
Пример оператора задержки с относительным значением:
delay 3.0; -- задержка на 3.0 секунды
Пример периодической задачи:
declare
use Ada.Calendar;
Next_Time : Time := Clock + Period;
-- Period – это глобальная константа типа Duration
begin
loop -- повторяется каждые Period секунд
delay until Next_Time;
... -- выполнить некоторые действия
Next_Time := Next_Time + Period;
end loop;
end;
use Ada.Calendar;
Next_Time : Time := Clock + Period;
-- Period – это глобальная константа типа Duration
begin
loop -- повторяется каждые Period секунд
delay until Next_Time;
... -- выполнить некоторые действия
Next_Time := Next_Time + Period;
end loop;
end;