D.15 Timing Events
1/2
{
AI95-00297-01}
This clause describes a language-defined package
to allow user-defined protected procedures to be executed at a specified
time without the need for a task or a delay statement.
Static Semantics
2/2
{
AI95-00297-01}
The following language-defined library package
exists:
3/2
package Ada.Real_Time.Timing_Events is
4/2
type Timing_Event is tagged limited private;
type Timing_Event_Handler
is access protected procedure (Event : in out Timing_Event);
5/2
procedure Set_Handler (Event : in out Timing_Event;
At_Time : in Time;
Handler : in Timing_Event_Handler);
procedure Set_Handler (Event : in out Timing_Event;
In_Time : in Time_Span;
Handler : in Timing_Event_Handler);
function Current_Handler (Event : Timing_Event)
return Timing_Event_Handler;
procedure Cancel_Handler (Event : in out Timing_Event;
Cancelled : out Boolean);
6/2
function Time_Of_Event (Event : Timing_Event) return Time;
7/2
private
... -- not specified by the language
end Ada.Real_Time.Timing_Events;
8/2
{
AI95-00297-01}
The type Timing_Event represents a time in the
future when an event is to occur. The type Timing_Event needs finalization
(see 7.6).
9/2
{
AI95-00297-01}
An object of type Timing_Event is said to be set
if it is associated with a non-null value of type Timing_Event_Handler
and cleared otherwise. All Timing_Event objects are initially
cleared.
10/2
{
AI95-00297-01}
The type Timing_Event_Handler identifies a protected
procedure to be executed by the implementation when the timing event
occurs. Such a protected procedure is called a handler.
10.a/2
Discussion:
Type Timing_Event 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 timing event object (this works because
a tagged type is a by-reference type). In more complex cases, a type
extension of type Timing_Event can be declared; a double type conversion
can be used to access the extension data. For example:
10.b/2
type Toaster_Timing_Event is new Timing_Event with record
Slot : Natural;
end record;
10.c/2
...
10.d/2
protected body Toaster is
10.e/2
procedure Timer (Event : in out Timing_Event) is
begin
Pop_Up_Toast (Toaster_Timing_Event(Timing_Event'Class(Event)).Slot);
end Timer;
10.f/2
...
end Toaster;
10.g/2
The extra conversion to
the class-wide type is necessary to make the conversions legal. While
this usage is clearly ugly, we think that the need for this sort of usage
will be rare, so we can live with it. It's certainly better than having
no way to associate data with an event.
Dynamic Semantics
11/3
{
AI95-00297-01}
{
AI05-0264-1}
The procedures Set_Handler associate the handler
Handler with the event Event:; if Handler is null, the event is cleared;, otherwise, it is set. The first procedure Set_Handler sets the execution time for
the event to be At_Time. The second procedure Set_Handler sets the execution
time for the event to be Real_Time.Clock + In_Time.
12/2
{
AI95-00297-01}
A call of a procedure Set_Handler for an event
that is already set replaces the handler and the time of execution; if
Handler is not null, the event remains set.
13/2
{
AI95-00297-01}
As soon as possible after the time set for the
event, the handler is executed, passing the event as parameter. The handler
is only executed if the timing event is in the set state at the time
of execution. The initial action of the execution of the handler is to
clear the event.
13.a/2
Reason: The second
sentence of this paragraph is because of a potential race condition.
The time might expire and yet before the handler is executed, some task
could call Cancel_Handler (or equivalently call Set_Handler with a null
parameter) and thus clear the handler.
14/2
{
AI95-00297-01}
If the Ceiling_Locking policy (see D.3)
is in effect when a procedure Set_Handler is called, a check is made
that the ceiling priority of Handler.all is Interrupt_Priority'Last.
If the check fails, Program_Error is raised.
15/3
{
AI95-00297-01}
{
AI05-0094-1}
{
AI05-0264-1}
If a procedure Set_Handler is called with zero
or negative In_Time or with At_Time indicating a time in the past, then the handler is executed as soon as
possible after the completion of immediately
by the task executing the call of
Set_Handler. The timing
event Event is cleared.
15.a/3
Ramification: {
AI05-0094-1}
The handler will still be executed. Under no circumstances
is a scheduled call of a handler lost.
15.b/3
Discussion: {
AI05-0094-1}
We say “as soon as possible” so that
we do not deadlock if we are executing the handler when Set_Handler is
called. In that case, the current invocation of the handler must complete
before the new handler can start executing.
16/3
{
AI95-00297-01}
{
AI05-0264-1}
The function Current_Handler returns the handler
associated with the event Event if that event is set; otherwise, it returns null.
17/3
{
AI95-00297-01}
{
AI05-0264-1}
The procedure Cancel_Handler clears the event if
it is set. Cancelled is assigned True if the event was set prior to it
being cleared; otherwise, it is assigned False.
18/3
{
AI95-00297-01}
{
AI05-0264-1}
The function Time_Of_Event returns the time of
the event if the event is set; otherwise, it returns Real_Time.Time_First.
19/2
{
AI95-00297-01}
As part of the finalization of an object of type
Timing_Event, the Timing_Event is cleared.
19.a/2
Implementation Note:
This is the only finalization defined by the language that has a
visible effect; but an implementation may have other finalization that
it needs to perform. Implementations need to ensure that the event is
cleared before anything else is finalized that would prevent a set event
from being triggered.
20/2
{
AI95-00297-01}
If several timing events are set for the same time,
they are executed in FIFO order of being set.
21/2
{
AI95-00297-01}
An exception propagated from a handler invoked
by a timing event has no effect.
Implementation Requirements
22/2
{
AI95-00297-01}
For a given Timing_Event object, the implementation
shall perform the operations declared in this package atomically with
respect to any of these operations on the same Timing_Event object. The
replacement of a handler by a call of Set_Handler shall be performed
atomically with respect to the execution of the handler.
22.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.
Metrics
23/2
{
AI95-00297-01}
The implementation shall document the following
metric:
24/3
{
AI05-0210-1}
An upper bound on the lateness of the execution
of a handler. That is, the maximum time between the
time specified for the event and when a
handler is actually invoked assuming no
other handler or task is executing during this interval executed
and the time specified when the event was set.
24.a/2
Documentation Requirement:
The metrics for timing events.
Implementation Advice
25/2
{
AI95-00297-01}
The protected handler procedure should be executed
directly by the real-time clock interrupt mechanism.
25.a/2
Implementation Advice:
For a timing event, the handler should
be executed directly by the real-time clock interrupt mechanism.
26/2
50 {
AI95-00297-01}
Since a call of Set_Handler is not a potentially
blocking operation, it can be called from within a handler.
27/2
51 {
AI95-00297-01}
A Timing_Event_Handler can be associated with several
Timing_Event objects.
Extensions to Ada 95
27.a/2
Wording Changes from Ada 2005
27.b/3
{
AI05-0094-1}
Correction: Reworded to eliminate a deadlock
condition if the event time is in the past and a handler is currently
executing. This is technically an inconsistency, but only if a program
is depending on deadlocking; since it is impossible to imagine how that
could be useful, we have not documented this as an inconsistency.
27.c/3
{
AI05-0210-1}
Correction: Clarified the metric for lateness
of a timing event to exclude interference from other handlers and tasks.
This change might change the documentation of an implementation, but
not the implementation itself, so there is no inconsistency.
Ada 2005 and 2012 Editions sponsored in part by Ada-Europe