Справочник по Ada (Ada 2022)
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 языка (см. ниже), типом Time в пакете Real_Time (см. D.8), или некоторым другим реализационно-определённым временным типом.
Статическая семантика
Существует предопределённый тип с фиксированной точкой, названный Duration, объявленный в видимой части пакета Standard; значение типа Duration используется для представления длительности временного интервала, выраженного в секундах. Тип Duration не привязан к определённой временной базе, но может быть использован с любой временной базой.
Значение типа Time в пакете Calendar или другого временного типа представляет время, отображаемое соответствующим таймером.
Существует следующий пакет библиотеки, определённый языком:
package Ada.Calendar
with Nonblocking, Global => in out synchronized 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 во временной базе, связанной с типом выражения. Для 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; она может также позволять представление и других дат (как более ранних, так и более поздних).
Разрешения для реализации
Реализация может определять дополнительные временные типы.
Реализация может вызывать Time_Error, если значение delay_expression в delay_until_statement select_statement представляет время более чем на 90 дней в будущем относительно текущего времени. Действительное ограничение, если таковое имеется, определяется реализацией.
Рекомендации по реализации
Всякий раз, когда это возможно в реализации, значение Duration'Small должно быть не больше 100 микросекунд.
Временная база для delay_relative_statement должна быть монотонной; она может отличаться от временной базы, используемой для Calendar.Clock.
ПРИМЕЧАНИЕ 1 Оператор delay_relative_statement с отрицательным значением выражения delay_expression эквивалентен оператору с нулевым значением.
END_OF_DOCUMENT_MARKER ПРИМЕЧАНИЕ 2 Выполнение delay_statement может быть выполнено задачей окружения; следовательно, delay_statementы могут быть выполнены в рамках разработки library_item или выполнения основной подпрограммы. Такие операторы приостанавливают задачу окружения (см. 10.2).
ПРИМЕЧАНИЕ 3 delay_statement является точкой завершения прерывания и потенциально блокирующей операцией, даже если задача фактически не заблокирована.
ПРИМЕЧАНИЕ 4 Не существует необходимой связи между System.Tick (разрешением часов пакета Calendar) и Duration'Small (small типа Duration).
ПРИМЕЧАНИЕ 5 Дополнительные требования, связанные с delay_statementы, приведены в D.9, «Точность задержки».
Примеры
Пример оператора относительной задержки:
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;