Language Ref Manual references: 9.4 Task Dependence - Termination of Tasks
|
In this section... 6.3.1 Avoiding Termination 6.3.2 Normal Termination 6.3.3 The Abort Statement 6.3.4 Abnormal Termination |
| Summary of Guidelines from this section |
Mode to Degraded still allowing execution of the system.
...
loop
Recognize_Degraded_Mode:
begin
if Mode = Primary then
select
Current_Position_Primary.Request_New_Coordinates
(X, Y);
or
delay 0.25;
-- Decide whether to switch modes;
end select;
else -- Mode = Degraded
Current_Position_Backup.Request_New_Coordinates
(X, Y);
end if;
...
exception
when Tasking_Error | Program_Error =>
Mode := Degraded;
end Recognize_Degraded_Mode;
end loop;
... |
'Terminated attribute to test a
task's availability before making the entry call can introduce a race
condition where the tested task fails after the test but before the entry call
(see Guideline 6.2.3).Language Ref Manual references: 9.5 Entries, Entry Calls, and Accept Statements, 11.2 Exception Handlers
---------------------------------------------------------------------
task body Message_Buffer is
...
begin -- Message_Buffer
loop
select
when Head /= Tail => -- Circular buffer not empty
accept Retrieve (Value : out Element) do
...
end Retrieve;
or
when not ((Head = Lower_Bound and then
Tail = Upper_Bound) or else
(Head /= Lower_Bound and then
Tail = Index'Pred(Head)) )
=> -- Circular buffer not full
accept Store (Value : in Element);
end select;
end loop;
...
end Message_Buffer;
--------------------------------------------------------------------- |
The effect of unterminated tasks at the end of program execution is undefined. A task dependent on a library package cannot be forced to terminate using a selective wait construct with terminate alternative and should be terminated explicitly during program shutdown. One way to terminate tasks dependent on library packages is to provide them with exit entries. Have the main subprogram call the exit entry just before it terminates.
Execution of an accept statement or of a selective wait statement without an else part, a delay, or a terminate alternative cannot proceed if no task ever calls the entry(s) associated with that statement. This could result in deadlock. Following this guideline entails programming multiple termination points in the task body. A reader can easily "know where to look" for the normal termination points in a task body. The termination points are the end of the body's sequence of statements, and alternatives of select statements.
If you are considering programming a task not to terminate, be certain that it is not a dependent of a block or subprogram from which the task's caller(s) will ever expect to return. Since entire programs can be candidates for reuse (see Chapter 8), note that the task (and whatever it depends upon) will not terminate. Also be certain that for any other task that you do wish to terminate, its termination does not await this task's termination. Reread and fully understand paragraph 9.4 of Department of Defense (1983) on "Task Dependence - Termination of Tasks."
Language Ref Manual references: 9.3 Task Execution - Task Activation, 9.5 Entries, Entry Calls, and Accept Statements, 9.7.1 Selective Waits
Tasks are not aborted until they reach a synchronization point such as beginning or end of elaboration, a delay statement, an accept statement, an entry call, a select statement, task allocation, or the execution of an exception handler. Consequently, the abort statement may not release processor resources as soon as you may expect. It also may not stop a runaway task because the task may be executing an infinite loop containing no synchronization points.
Language Ref Manual references: 9.1 Abort Statements
others at the end of a task body.
---------------------------------------------------------------------
task body Track is
My_Index : Track_Index;
Neutral : Boolean := True;
begin -- Track
select
accept Start (Who_Am_I : in Track_Index) do
My_Index := Who_Am_I;
end Start;
Neutral := False;
...
or
terminate;
end select;
...
exception
when others =>
if not Neutral then
Station(My_Index).Status := Dead;
end if;
end Track;
--------------------------------------------------------------------- |
others, ensures that a
task can regain control after an exception occurs. If the task cannot proceed
normally after handling an exception, this affords it the opportunity to shut
itself down cleanly and to notify tasks responsible for error recovery
necessitated by the abnormal termination of the task.
Tasking_Error exception raised by the call
to an entry of an abnormal task (see Guideline 6.3.1).Language Ref Manual references: 9.1 Abort Statements, 11.2 Exception Handlers, 11.4 Exception Handling