Next: , Previous: D.14, Up: D.14


D.14.1 Execution Time Timers

1/2
{00307AI95−00307−01} This clause describes a language−defined package that provides a facility for calling a handler when a task has used a defined amount of CPU time.

Static Semantics

2/2
{00307AI95−00307−01} The following language−defined library package exists:

3/2

     with System;
     package Ada.Execution_Time.Timers is

4/2

        type Timer (T not null access constant
                            Ada.Task_Identification.Task_Id) is
           tagged limited private;

5/2

        type Timer_Handler is
           access protected procedure (TM in out Timer);

6/2

        Min_Handler_Ceiling constant System.Any_Priority :=
        implementation−defined;

7/2

        procedure Set_Handler (TM      in out Timer;
                               In_Time in Time_Span;
                               Handler in Timer_Handler);
        procedure Set_Handler (TM      in out Timer;
                               At_Time in CPU_Time;
                               Handler in Timer_Handler);
        function Current_Handler (TM Timer) return Timer_Handler;
        procedure Cancel_Handler (TM        in out Timer;
                                  Cancelled    out Boolean);

8/2

        function Time_Remaining (TM Timer) return Time_Span;

9/2

        Timer_Resource_Error exception;

10/2

     private
        ... −−  not specified by the language
     end Ada.Execution_Time.Timers;

11/2
{00307AI95−00307−01} The type Timer represents an execution−time event for a single task and is capable of detecting execution−time overruns. The access discriminant T identifies the task concerned. The type Timer needs finalization (see 7.6).

12/2
{00307AI95−00307−01} An object of type Timer is said to be set if it is associated with a non−null value of type Timer_Handler and cleared otherwise. All Timer objects are initially cleared. {set (execution timer object) [partial]} {clear (execution timer object) [partial]} 13/2
{00307AI95−00307−01} The type Timer_Handler identifies a protected procedure to be executed by the implementation when the timer expires. Such a protected procedure is called a handler. {handler (execution timer) [partial]} 13.a/2

Discussion: Type Timer is tagged. This makes it possible to share a handler between several events. In simple cases, 'Access can be used to compare the parameter with a specific timer object (this works because a tagged type is a by−reference type). In more complex cases, a type extension of type Timer can be declared; a double type conversion can be used to access the extension data. An example of how this can be done can be found for the similar type Timing_Event, see D.15.
Dynamic Semantics

14/2
{00307AI95−00307−01} When a Timer object is created, or upon the first call of a Set_Handler procedure with the timer as parameter, the resources required to operate an execution−time timer based on the associated execution−time clock are allocated and initialized. If this operation would exceed the available resources, Timer_Resource_Error is raised.

15/2
{00307AI95−00307−01} The procedures Set_Handler associate the handler Handler with the timer TM; if Handler is null, the timer is cleared, otherwise it is set. The first procedure Set_Handler loads the timer TM with an interval specified by the Time_Span parameter. In this mode, the timer TM expires when the execution time of the task identified by TM.T.all has increased by In_Time; if In_Time is less than or equal to zero, the timer expires immediately. The second procedure Set_Handler loads the timer TM with the absolute value specified by At_Time. In this mode, the timer TM expires when the execution time of the task identified by TM.T.all reaches At_Time; if the value of At_Time has already been reached when Set_Handler is called, the timer expires immediately.{expires (execution timer)} 15.a/2

Implementation Note: Since an access−to−constant can designate a variable, the Task_Id value designated by the discriminant of a Timer object can be changed after the object is created. Thus, an implementation cannot use the value of the Task_Id other than where this Standard specifies. For instance, the Task_Id should be read when the timer is set, but it should not be used when the timer expires (as it may designate a different task at that point.

16/2
{00307AI95−00307−01} A call of a procedure Set_Handler for a timer that is already set replaces the handler and the (absolute or relative) execution time; if Handler is not null, the timer remains set.

17/2
{00307AI95−00307−01} When a timer expires, the associated handler is executed, passing the timer as parameter. The initial action of the execution of the handler is to clear the event.

18/2
{00307AI95−00307−01} The function Current_Handler returns the handler associated with the timer TM if that timer is set; otherwise it returns null.

19/2
{00307AI95−00307−01} The procedure Cancel_Handler clears the timer if it is set. Cancelled is assigned True if the timer was set prior to it being cleared; otherwise it is assigned False.

20/2
{00307AI95−00307−01} The function Time_Remaining returns the execution time interval that remains until the timer TM would expire, if that timer is set; otherwise it returns Time_Span_Zero.

21/2
{00307AI95−00307−01} The constant Min_Handler_Ceiling is the minimum ceiling priority required for a protected object with a handler to ensure that no ceiling violation will occur when that handler is invoked.

22/2
{00307AI95−00307−01} As part of the finalization of an object of type Timer, the timer is cleared.

23/2
{00307AI95−00307−01} For all the subprograms defined in this package, Tasking_Error is raised if the task identified by TM.T.all has terminated, and Program_Error is raised if the value of TM.T.all is Task_Identification.Null_Task_Id.

24/2
{00307AI95−00307−01} An exception propagated from a handler invoked as part of the expiration of a timer has no effect.

Erroneous Execution

25/2
{00307AI95−00307−01} {erroneous execution (cause) [partial]} For a call of any of the subprograms defined in this package, if the task identified by TM.T.all no longer exists, the execution of the program is erroneous.

Implementation Requirements

26/2
{00307AI95−00307−01} For a given Timer object, the implementation shall perform the operations declared in this package atomically with respect to any of these operations on the same Timer object. The replacement of a handler by a call of Set_Handler shall be performed atomically with respect to the execution of the handler.

26.a/2

Reason: This prevents various race conditions. In particular it ensures that if an event occurs when Set_Handler is changing the handler then either the new or old handler is executed in response to the appropriate event. It is never possible for a new handler to be executed in response to an old event

27/2
{00307AI95−00307−01} When an object of type Timer is finalized, the system resources used by the timer shall be deallocated.

Implementation Permissions

28/2
{00307AI95−00307−01} Implementations may limit the number of timers that can be defined for each task. If this limit is exceeded then Timer_Resource_Error is raised.

     NOTES

29/2

42  {00307AI95−00307−01} A Timer_Handler can be associated with several Timer objects.
Extensions to Ada 95

29.a/2

{00307AI95−00307−01} {extensions to Ada 95} The package Execution_Time.Timers is new.