Руководство по Ada (Ada 2022)
D.8 Монотонное время
Этот подпункт описывает пакет высокоточного монотонного таймера.
Статическая семантика
Существует следующий определяемый языком библиотечный пакет:
package Ada.Real_Time
with Nonblocking, Global => in out synchronized is
with Nonblocking, Global => in out synchronized is
type Time is private;
Time_First : constant Time;
Time_Last : constant Time;
Time_Unit : constant := значение, определяемое реализацией;
Time_First : constant Time;
Time_Last : constant Time;
Time_Unit : constant := значение, определяемое реализацией;
type Time_Span is private;
Time_Span_First : constant Time_Span;
Time_Span_Last : constant Time_Span;
Time_Span_Zero : constant Time_Span;
Time_Span_Unit : constant Time_Span;
Time_Span_First : constant Time_Span;
Time_Span_Last : constant Time_Span;
Time_Span_Zero : constant Time_Span;
Time_Span_Unit : constant Time_Span;
Tick : constant Time_Span;
function Clock return Time;
function Clock return Time;
function "+" (Left : Time; Right : Time_Span) return Time;
function "+" (Left : Time_Span; Right : Time) return Time;
function "-" (Left : Time; Right : Time_Span) return Time;
function "-" (Left : Time; Right : Time) return Time_Span;
function "+" (Left : Time_Span; Right : Time) return Time;
function "-" (Left : Time; Right : Time_Span) return Time;
function "-" (Left : Time; Right : Time) return Time_Span;
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;
function "+" (Left, Right : Time_Span) return Time_Span;
function "-" (Left, Right : Time_Span) return Time_Span;
function "-" (Right : Time_Span) return Time_Span;
function "*" (Left : Time_Span; Right : Integer) return Time_Span;
function "*" (Left : Integer; Right : Time_Span) return Time_Span;
function "/" (Left, Right : Time_Span) return Integer;
function "/" (Left : Time_Span; Right : Integer) return Time_Span;
function "-" (Left, Right : Time_Span) return Time_Span;
function "-" (Right : Time_Span) return Time_Span;
function "*" (Left : Time_Span; Right : Integer) return Time_Span;
function "*" (Left : Integer; Right : Time_Span) return Time_Span;
function "/" (Left, Right : Time_Span) return Integer;
function "/" (Left : Time_Span; Right : Integer) return Time_Span;
function "abs"(Right : Time_Span) return Time_Span;
Этот абзац был удалён.
function "<" (Left, Right : Time_Span) return Boolean;
function "<="(Left, Right : Time_Span) return Boolean;
function ">" (Left, Right : Time_Span) return Boolean;
function ">="(Left, Right : Time_Span) return Boolean;
function "<="(Left, Right : Time_Span) return Boolean;
function ">" (Left, Right : Time_Span) return Boolean;
function ">="(Left, Right : Time_Span) return Boolean;
function To_Duration (TS : Time_Span) return Duration;
function To_Time_Span (D : Duration) return Time_Span;
function To_Time_Span (D : Duration) return Time_Span;
function Nanoseconds (NS : Integer) return Time_Span;
function Microseconds (US : Integer) return Time_Span;
function Milliseconds (MS : Integer) return Time_Span;
function Seconds (S : Integer) return Time_Span;
function Minutes (M : Integer) return Time_Span;
function Microseconds (US : Integer) return Time_Span;
function Milliseconds (MS : Integer) return Time_Span;
function Seconds (S : Integer) return Time_Span;
function Minutes (M : Integer) return Time_Span;
type Seconds_Count is range значение, определяемое реализацией;
procedure Split(T : in Time; SC : out Seconds_Count; TS : out Time_Span);
function Time_Of(SC : Seconds_Count; TS : Time_Span) return Time;
function Time_Of(SC : Seconds_Count; TS : Time_Span) return Time;
private
... -- не определяется языком
end Ada.Real_Time;
... -- не определяется языком
end Ada.Real_Time;
В этом приложении, реальное время определяется как физическое время, наблюдаемое во внешней среде. Тип Time — это тип времени, как определено в 9.6; значения этого типа могут быть использованы в delay_until_statement. Значения этого типа представляют сегменты идеальной временной оси. Множество значений типа Time взаимно однозначно соответствует диапазону значений математических целых чисел, определяемому реализацией.
Значение Time I представляет полуоткрытый интервал реального времени, начинающийся с E+I*Time_Unit и ограниченный E+(I+1)*Time_Unit, где Time_Unit — определяемое реализацией вещественное число, а E — неопределённая начальная точка, эпоха, одинаковая для всех значений типа Time. Язык не определяет, синхронизированы ли значения времени с какой-либо стандартной временной отметкой. Например, E может соответствовать времени запуска системы или эпохе какого-либо временного стандарта.
Значения типа Time_Span представляют длительность интервала реального времени. Множество значений этого типа взаимно однозначно соответствует диапазону значений математических целых чисел, определяемому реализацией. Значение Time_Span, соответствующее целому числу I, представляет продолжительность реального времени I*Time_Unit.
Time_First и Time_Last — это наименьшее и наибольшее значения типа Time соответственно. Аналогично, Time_Span_First и Time_Span_Last — это наименьшее и наибольшее значения типа Time_Span соответственно.
Значение типа Seconds_Count представляет прошедшее время, измеренное в секундах, с момента эпохи.
Динамическая семантика
Time_Unit — наименьший интервал реального времени, представимый типом Time; он выражен в секундах. Time_Span_Unit — разность между двумя последовательными значениями типа Time. Это также наименьшее положительное значение типа Time_Span. Time_Unit и Time_Span_Unit представляют одинаковую продолжительность реального времени. Такт таймера — интервал реального времени, в течение которого значение таймера (наблюдаемое при вызове функции Clock) остаётся постоянным. Tick — средняя продолжительность таких интервалов.
Функция To_Duration преобразует значение TS в значение типа Duration. Аналогично, функция To_Time_Span преобразует значение D в значение типа Time_Span. Для To_Duration результат округляется до ближайшего значения типа Duration (в сторону от нуля, если ровно посередине между двумя значениями). Если результат выходит за пределы диапазона Duration, возникает исключение Constraint_Error. Для To_Time_Span значение D сначала округляется до ближайшего целого кратного Time_Unit, в сторону от нуля, если ровно посередине между двумя кратными. Если округлённое значение выходит за пределы диапазона Time_Span, возникает исключение Constraint_Error. В противном случае значение преобразуется в тип Time_Span.
To_Duration(Time_Span_Zero) возвращает 0,0, а To_Time_Span(0,0) возвращает Time_Span_Zero.
Функции Nanoseconds, Microseconds, Milliseconds, Seconds и Minutes преобразуют входной параметр в значение типа Time_Span. NS, US, MS, S и M интерпретируются как количество наносекунд, микросекунд, миллисекунд, секунд и минут соответственно. Входной параметр сначала преобразуется в секунды и округляется до ближайшего целого кратного Time_Unit, в сторону от нуля, если ровно посередине между двумя кратными. Если округлённое значение выходит за пределы диапазона Time_Span, возникает исключение Constraint_Error. В противном случае округлённое значение преобразуется в тип Time_Span.
Эффекты операторов над Time и Time_Span такие же, как для операторов, определённых для целочисленных типов.
Функция Clock возвращает количество времени, прошедшее с момента эпохи.
Эффекты операций Split и Time_Of определяются следующим образом, рассматривая значения типа Time, Time_Span и Seconds_Count как математические целые числа. Эффект Split(T,SC,TS) состоит в установке SC и TS в такие значения, чтобы T*Time_Unit = SC*1.0 + TS*Time_Unit, и 0.0 <= TS*Time_Unit < 1.0. Возвращаемое значение Time_Of(SC,TS) — это значение T такое, что T*Time_Unit = SC*1.0 + TS*Time_Unit.
Требования к реализации
Диапазон значений Time должен быть достаточен для уникального представления интервала времени с момента запуска программы до 50 лет спустя. Tick должен быть не больше 1 миллисекунды. Time_Unit должно быть меньше или равно 20 микросекундам.
Значение Time_Span_First в секундах должно быть не больше –3600, а значение Time_Span_Last в секундах — не меньше 3600.
Скачок таймера — разность между двумя последовательными различными значениями таймера (наблюдаемыми при вызове функции Clock). Не должно быть обратных скачков таймера.
Требования к документации
Реализация должна документировать значения Time_First, Time_Last, Time_Span_First, Time_Span_Last, Time_Span_Unit и Tick.
Реализация должна документировать свойства базового временного базиса, используемого для таймера и типа Time, такие как поддерживаемый диапазон значений и все относящиеся аспекты используемого базового оборудования или системных средств.
Реализация должна документировать наличие или отсутствие синхронизации с внешними временными отметками, и если такая синхронизация существует, источники синхронизирующей информации, частоту синхронизации и применяемый метод синхронизации.
Реализация должна документировать любые аспекты внешней среды, которые могут повлиять на поведение таймера, как определено в этом подпункте.
Метрики
Для целей определенных в этом подпункте метрик, реальное время определяется как Международное Атомное Время (TAI).
Реализация должна документировать следующие метрики:
- Верхняя граница продолжительности интервала реального времени такта таймера. Это значение D такое, что если t1 и t2 — любые реальные времена такие, что t1 < t2 и Clockt1 = Clockt2, то t2 – t1 <= D.
- Верхняя граница размера скачка таймера.
- Верхняя граница скорости дрейфа Clock относительно реального времени. Это вещественное число D такое, что
E*(1–D) <= (Clockt+E – Clockt) <= E*(1+D)
при условии: Clockt + E*(1+D) <= Time_Last.
при условии: Clockt + E*(1+D) <= Time_Last.
- где Clockt — значение Clock в момент времени t, а E — реальная длительность времени не менее 24 часов. Значение E, используемое для этой метрики, должно быть указано.
- Верхняя граница времени выполнения вызова функции Clock в тактах процессора.
- Верхние границы времени выполнения операций типов Time и Time_Span в тактах процессора.
Разрешения для реализации
Реализации, предназначенные для машин со размером слова меньше 32 бит, могут опустить поддержку полного диапазона и гранулярности типов Time и Time_Span.
Рекомендации по реализации
При необходимости реализации должны предоставлять механизмы конфигурации для изменения значения Tick.
Рекомендуется, чтобы Calendar.Clock и Real_Time.Clock реализовывались как преобразования одной и той же временной базы.
Рекомендуется, чтобы «лучшая» временная база, существующая в базовой системе, была доступна приложению через Clock. «Лучшая» может означать наивысшую точность или наибольший диапазон.
ПРИМЕЧАНИЕ 1 Правила в этом подпункте не подразумевают, что реализация может защитить пользователя от ошибок оператора или установки, которые могут привести к неверному установлению часов.
ПРИМЕЧАНИЕ 2 Time_Unit — это гранулярность типа Time. В противоположность этому, Tick представляет гранулярность Real_Time.Clock. Нет требования, чтобы они были одинаковыми.