Annotated Ada Reference Manual (Ada 202y Draft 1)Legal Information
Contents   Index   References   Search   Previous   Next 

9.6 Delay Statements, Duration, and Time

1
[ A delay_statement is used to block further execution until a specified expiration time is reached. The expiration time can be specified either as a particular point in time (in a delay_until_statement), or in seconds from the current time (in a delay_relative_statement). The language-defined package Calendar provides definitions for a type Time and associated operations, including a function Clock that returns the current time. ]

Syntax

2
delay_statement ::= delay_until_statement | delay_relative_statement
3
delay_until_statement ::= delay until delay_expression;
4
delay_relative_statement ::= delay delay_expression;

Name Resolution Rules

5
The expected type for the delay_expression in a delay_relative_statement is the predefined type Duration. The delay_expression in a delay_until_statement is expected to be of any nonlimited type.

Legality Rules

6/3
{AI05-0092-1} There can be multiple time bases, each with a corresponding clock, and a corresponding time type. The type of the delay_expression in a delay_until_statement shall be a time type — either the type Time defined in the language-defined package Calendar (see below), the type Time in the package Real_Time (see D.8), or some other implementation-defined time type. 
6.a
Implementation defined: Any implementation-defined time types.

Static Semantics

7
[There is a predefined fixed point type named Duration, declared in the visible part of package Standard;] a value of type Duration is used to represent the length of an interval of time, expressed in seconds. [The type Duration is not specific to a particular time base, but can be used with any time base.]
8/3
{AI05-0092-1} A value of the type Time in package Calendar, or of some other time type, represents a time as reported by a corresponding clock.
9
The following language-defined library package exists: 
10/5
{AI12-0241-1} {AI12-0302-1}
package Ada.Calendar 
  with Nonblocking, Global => in out synchronized is
  type Time is private;
11/2
{AI95-00351-01}   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;
11.a/2
Reason: {AI95-00351-01} A range of 500 years was chosen, as that only requires one extra bit for the year as compared to Ada 95. This was done to minimize disruptions with existing implementations. (One implementor reports that their time values represent nanoseconds, and this year range requires 63.77 bits to represent.) 
12
  function Clock return Time;
13
  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;
14
  procedure Split (Date  : in Time;
                   Year    : out Year_Number;
                   Month   : out Month_Number;
                   Day     : out Day_Number;
                   Seconds : out Day_Duration);
15
  function Time_Of(Year  : Year_Number;
                   Month   : Month_Number;
                   Day     : Day_Number;
                   Seconds : Day_Duration := 0.0)
    return Time;
16
  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;
17
  function "<" (Left, Right : Time) return Boolean;
  function "<="(Left, Right : Time) return Boolean;
  function ">" (Left, Right : Time) return Boolean;
  function ">="(Left, Right : Time) return Boolean;
18
  Time_Error : exception;
19
private
   ... -- not specified by the language
end Ada.Calendar;

Dynamic Semantics

20
For the execution of a delay_statement, the delay_expression is first evaluated. For a delay_until_statement, the expiration time for the delay is the value of the delay_expression, in the time base associated with the type of the expression. For a delay_relative_statement, the expiration time is defined as the current time, in the time base associated with relative delays, plus the value of the delay_expression converted to the type Duration, and then rounded up to the next clock tick. The time base associated with relative delays is as defined in D.9, “Delay Accuracy” or is implementation defined. 
20.a
Implementation defined: The time base associated with relative delays.
20.b
Ramification: Rounding up to the next clock tick means that the reading of the delay-relative clock when the delay expires should be no less than the current reading of the delay-relative clock plus the specified duration. 
21
The task executing a delay_statement is blocked until the expiration time is reached, at which point it becomes ready again. If the expiration time has already passed, the task is not blocked. 
21.a
Discussion: For a delay_relative_statement, this case corresponds to when the value of the delay_expression is zero or negative.
21.b
Even though the task is not blocked, it might be put back on the end of its ready queue. See D.2, “Priority Scheduling”. 
22/3
{AI05-0092-1} If an attempt is made to cancel the delay_statement [(as part of an asynchronous_select or abort — see 9.7.4 and 9.8)], the statement is cancelled if the expiration time has not yet passed, thereby completing the delay_statement.
22.a
Reason: This is worded this way so that in an asynchronous_select where the triggering_statement is a delay_statement, an attempt to cancel the delay when the abortable_part completes is ignored if the expiration time has already passed, in which case the optional statements of the triggering_alternative are executed. 
23
The time base associated with the type Time of package Calendar is implementation defined. The function Clock of package Calendar returns a value representing the current time for this time base. [The implementation-defined value of the named number System.Tick (see 13.7) is an approximation of the length of the real-time interval during which the value of Calendar.Clock remains constant.] 
23.a
Implementation defined: The time base of the type Calendar.Time.
24/2
{AI95-00351-01} The functions Year, Month, Day, and Seconds return the corresponding values for a given value of the type Time, as appropriate to an implementation-defined time zone; the procedure Split returns all four corresponding values. Conversely, the function Time_Of combines a year number, a month number, a day number, and a duration, into a value of type Time. The operators "+" and "–" for addition and subtraction of times and durations, and the relational operators for times, have the conventional meaning. 
24.a/2
Implementation defined: The time zone used for package Calendar operations.
24.b/3
Ramification: {AI05-0119-1} The behavior of these values and subprograms if the time zone changes is also implementation-defined. In particular, the changes associated with summer time adjustments (like Daylight Savings Time in the United States) should be treated as a change in the implementation-defined time zone. The language does not specify whether the time zone information is stored in values of type Time; therefore the results of binary operators are unspecified when the operands are the two values with different effective time zones. In particular, the results of "-" may differ from the "real" result by the difference in the time zone adjustment. Similarly, the result of UTC_Time_Offset (see 9.6.1) may or may not reflect a time zone adjustment. 
25
If Time_Of is called with a seconds value of 86_400.0, the value returned is equal to the value of Time_Of for the next day with a seconds value of 0.0. The value returned by the function Seconds or through the Seconds parameter of the procedure Split is always less than 86_400.0.
26/1
{8652/0030} {AI95-00113-01} The exception Time_Error is raised by the function Time_Of if the actual parameters do not form a proper date. This exception is also raised by the operators "+" and "–" if the result is not representable in the type Time or Duration, as appropriate. This exception is also raised by the functions Year, Month, Day, and Seconds and the procedure Split if the year number of the given date is outside of the range of the subtype Year_Number. 
26.a/1
To be honest: {8652/0106} {AI95-00160-01} By "proper date" above we mean that the given year has a month with the given day. For example, February 29th is a proper date only for a leap year. We do not mean to include the Seconds in this notion; in particular, we do not mean to require implementations to check for the “missing hour” that occurs when Daylight Savings Time starts in the spring. 
26.b/2
Reason: {8652/0030} {AI95-00113-01} {AI95-00351-01} We allow Year and Split to raise Time_Error because the arithmetic operators are allowed (but not required) to produce times that are outside the range of years from 1901 to 2399. This is similar to the way integer operators may return values outside the base range of their type so long as the value is mathematically correct. We allow the functions Month, Day and Seconds to raise Time_Error so that they can be implemented in terms of Split. 

Implementation Requirements

27
The implementation of the type Duration shall allow representation of time intervals (both positive and negative) up to at least 86400 seconds (one day); Duration'Small shall not be greater than twenty milliseconds. The implementation of the type Time shall allow representation of all dates with year numbers in the range of Year_Number[; it may allow representation of other dates as well (both earlier and later).] 

Implementation Permissions

28/3
{AI05-0092-1} An implementation may define additional time types.
29
An implementation may raise Time_Error if the value of a delay_expression in a delay_until_statement of a select_statement represents a time more than 90 days past the current time. The actual limit, if any, is implementation-defined. 
29.a
Implementation defined: Any limit on delay_until_statements of select_statements.
29.b
Implementation Note: This allows an implementation to implement select_statement timeouts using a representation that does not support the full range of a time type. In particular 90 days of seconds can be represented in 23 bits, allowing a signed 24-bit representation for the seconds part of a timeout. There is no similar restriction allowed for stand-alone delay_until_statements, as these can be implemented internally using a loop if necessary to accommodate a long delay. 

Implementation Advice

30
Whenever possible in an implementation, the value of Duration'Small should be no greater than 100 microseconds. 
30.a
Implementation Note: This can be satisfied using a 32-bit 2's complement representation with a small of 2.0**(–14) — that is, 61 microseconds — and a range of ± 2.0**17 — that is, 131_072.0. 
30.b/2
Implementation Advice: The value of Duration'Small should be no greater than 100 microseconds.
31/5
{AI12-0444-1} The time base for delay_relative_statements should be monotonic; it can be different than the time base as used for Calendar.Clock. 
31.a/2
Implementation Advice: The time base for delay_relative_statements should be monotonic.
32
NOTE 1   A delay_relative_statement with a negative value of the delay_expression is equivalent to one with a zero value.
33/5
NOTE 2   {AI12-0440-1} A delay_statement can be executed by the environment task; consequently delay_statements can be executed as part of the elaboration of a library_item or the execution of the main subprogram. Such statements delay the environment task (see 10.2).
34
NOTE 3   A delay_statement is an abort completion point and a potentially blocking operation, even if the task is not actually blocked.
35
NOTE 4   There is no necessary relationship between System.Tick (the resolution of the clock of package Calendar) and Duration'Small (the small of type Duration). 
35.a
Ramification: The inaccuracy of the delay_statement has no relation to System.Tick. In particular, it is possible that the clock used for the delay_statement is less accurate than Calendar.Clock.
35.b
We considered making Tick a run-time-determined quantity, to allow for easier configurability. However, this would not be upward compatible, and the desired configurability can be achieved using functionality defined in Annex D, “Real-Time Systems”. 
36
NOTE 5   Additional requirements associated with delay_statements are given in D.9, “Delay Accuracy”.

Examples

37
Example of a relative delay statement: 
38
delay 3.0;  -- delay 3.0 seconds
39
Example of a periodic task: 
40
declare
   use Ada.Calendar;
   Next_Time : Time := Clock + Period;
                      -- Period is a global constant of type Duration
begin
   loop               -- repeated every Period seconds
      delay until Next_Time;
      ... -- perform some actions
      Next_Time := Next_Time + Period;
   end loop;
end;

Inconsistencies With Ada 83

40.a
For programs that raise Time_Error on "+" or "–" in Ada 83,the exception might be deferred until a call on Split or Year_Number, or might not be raised at all (if the offending time is never Split after being calculated). This should not affect typical programs, since they deal only with times corresponding to the relatively recent past or near future. 

Extensions to Ada 83

40.b
The syntax rule for delay_statement is modified to allow delay_until_statements.
40.c/2
{AI95-00351-01} The type Time may represent dates with year numbers outside of Year_Number. Therefore, the operations "+" and "–" need only raise Time_Error if the result is not representable in Time (or Duration); also, Split or Year will now raise Time_Error if the year number is outside of Year_Number. This change is intended to simplify the implementation of "+" and "–" (allowing them to depend on overflow for detecting when to raise Time_Error) and to allow local time zone information to be considered at the time of Split rather than Clock (depending on the implementation approach). For example, in a POSIX environment, it is natural for the type Time to be based on GMT, and the results of procedure Split (and the functions Year, Month, Day, and Seconds) to depend on local time zone information. In other environments, it is more natural for the type Time to be based on the local time zone, with the results of Year, Month, Day, and Seconds being pure functions of their input.
40.d/2
This paragraph was deleted.{AI95-00351-01}

Inconsistencies With Ada 95

40.e/2
{AI95-00351-01} The upper bound of Year_Number has been changed to avoid a year 2100 problem. A program which expects years past 2099 to raise Constraint_Error will fail in Ada 2005. We don't expect there to be many programs which are depending on an exception to be raised. A program that uses Year_Number'Last as a magic number may also fail if values of Time are stored outside of the program. Note that the lower bound of Year_Number wasn't changed, because it is not unusual to use that value in a constant to represent an unknown time. 

Wording Changes from Ada 95

40.f/2
{8652/0002} {AI95-00171-01} Corrigendum: Clarified that Month, Day, and Seconds can raise Time_Error. 

Contents   Index   References   Search   Previous   Next 
Ada-Europe Ada 2005 and 2012 Editions sponsored in part by Ada-Europe