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