CVS difference for ais/ai-10266.txt

Differences between 1.7 and version 1.8
Log of other versions for file ais/ai-10266.txt

--- ais/ai-10266.txt	2003/07/26 03:26:03	1.7
+++ ais/ai-10266.txt	2003/09/19 01:42:29	1.8
@@ -1,4 +1,4 @@
-!standard D.2.2 (5)                                03-06-05  AI95-00266-02/03
+!standard D.2.2 (5)                                03-08-17  AI95-00266-02/04
 !standard D.7 (00)
 !class amendment 01-06-01
 !status work item 01-06-01
@@ -9,14 +9,14 @@
 
 !summary
 
-A mechanism is proposed for associating protected procedures
-with a task. These procedures are invoked when the task is about to terminate
-(either normally, as a result of an unhandled exception or due to abortion).
+A mechanism is proposed for associating a protected procedure
+with a task. This procedure is invoked when the task is about to terminate
+(either normally, as a result of an unhandled exception or due to abort).
 If a task terminates due to an unhandled exception, the exception occurrence
 is passed as a parameter to the procedure. The proposal provides an alternative
 to that of AI95-00266-01 which was rejected by IRTAW11; it responds to earlier
-comments by the the ARG. The proposal here introduces default handlers,
-but does not go as far as task groups.
+comments by the ARG. The proposal here introduces default handlers for task
+hierarchies, but does not go as far as task groups.
 
 !problem
 
@@ -30,40 +30,34 @@
 with Ada.Task_Identification; use Task_Identification;
 with Ada.Exceptions; use Ada.Exceptions;
 package Ada.Task_Termination is
+  type Cause is (Normal, Abnormal, Unhandled_Exception);
 
-  type Protected_Termination_Handler is access protected procedure(
-              Id: Task_Id);
+  type Handler is access protected procedure(
+    C: Cause; Id: Task_Id; X: Exception_Occurrence := Null_Id);
+    -- Null_Id is used when cause is not Unhandler_Exception
+
+  procedure Set_Dependents_Default_Handler(New_Handler: in Handler);
+    -- Sets the default handler for all task dependents.
+    -- Handlers are not set on blocks, only on tasks
+    --
+    -- New_Handler is called immediately prior to dependent task termination.
+    -- If the task completed due to completing the last statement
+    -- of the task body, or as part of waiting on a terminate
+    -- alternative then C is set to Normal and no exception id
+    -- is given. If termination is due to abort then C is set
+    -- to Abnormal and no exception id is given. If termination is
+    -- due to a unhandled exception then C is set to Unhandled_
+    -- Exception and the associated exception id is set.
+
+  procedure Get_Handler(Old_Handler: out Handler);
+    -- Returns the previously set handler, or default or null.
+
+  procedure Set_Handler(Id : Task_Id; New_Handler: in Handler;
+            Old_Handler : out Handler);
+    -- A handler is set for the task; overriding any default. Old_Handler
+    -- returns any previously set handler, or default handler or null.
+    -- If a null handler is set then thsi re-estabilishes the default.
 
-  type Protected_Exceptional_Termination_Handler is access protected procedure(
-              Id: Task_Id; X: Exception_Occurrence);
-
-  procedure Set_Normal_Termination_Handler(
-                New_Handler: in Protected_Termination_Handler;
-                Old_Handler: out Protected_Termination_Handler;
-                Id : in Task_Id := Null_Task_Id);
-              -- New_Handler is called immediately prior to task termination,
-              -- if the task completed due to completing the last statement
-              -- of the task body, or as part of waiting on a terminate
-              -- alternative. If Task_Id = Null_Task_Id then a default
-	      -- handler is defined.
-
-  procedure Set_Unhandled_Exception_Handler(
-                New_Handler: in Protected_Exceptional_Termination_Handler;
-                Old_Handler: out Protected_Termination_Handler;
-                Id : in Task_Id := Null_Task_Id);
-              -- New_Handler is called immediately prior to task termination,
-              -- if the task completed due to an unhandled exception
-              -- during execution or activation. If Task_Id = Null_Task_Id
-	      -- then a default handler is defined.
-
-  procedure Set_Abnormal_Termination_Handler(
-                New_Handler: in Protected_Termination_Handler;
-                Old_Handler: out Protected_Termination_Handler;
-                Id : in Task_Id := Null_Task_Id);
-              -- New_Handler is called immediately prior to task termination,
-              -- if the task completed due to abortion.If Task_Id = Null_Task_Id
-	      -- then a default handler is defined.
-
 end Ada.Task_Termination;
 
 !wording
@@ -80,8 +74,6 @@
 at the general language level but it is also appropriate for a
 Ravenscar environment.
 
-The package could be a child of Ada.Task_Identification.
-
 The primary goal of this proposal is to address only the issue of silent
 termination. Consequently, the proposal does not address issues of
 termination as a result of failures after task creation but before task
@@ -95,23 +87,27 @@
 
 This proposal allows defaults (for the active partition) to be assigned
 for all tasks; or per-task handlers to be set. It does not attempt to
-define task groups. If a different AI were to propose a means of sensibly
-grouping tasks together then it would be possible to extend the provisions
-defined here. To give some level of support for composability the old
-handler is returned when a new one is set. This could be null if there
-is no previous handler.
+define task groups. But a default is for all dependent tasks. Hence setting
+the default for the environment task will cover all tasks in the partition.
+
+With a task hierarchy two programming styles are possible. The first
+involves replacing the default for a part of the tree - this is directly
+supported by the proposal. The second involves adding to the existing
+default - this can be programmed by first getting the original default
+and then creating a new handler that incorporates the new functionality
+plus a call to the original handler. Note this would be much easier to
+program with an extendable protected type!
 
-When any of the protected subprograms are set and the task
+When a call on Set_Handler is made and the task
 has already terminated then the handler is executed immediately.
 
-If a null handler is set then this is equivalent to there being no
-handler.
+If a null default handler is set then this is equivalent to there being
+no handler.
 
 The requirement is that the user-supplied protected subprogram is usually
 called after the task has been finalized but on the stack of the terminating
-task. Consequently, if Task_Identification.Current_Task is called from one of
-the subprograms, the terminating task identifier is returned.
-
+task. Consequently, if Task_Identification.Current_Task is called from the
+handler, the terminating task identifier is returned.
 If the task has already terminated, the handler is called on the stack
 of the calling task, and Task_Identification.Current_Task
 returns the calling task.
@@ -123,51 +119,60 @@
 
 The following example illustrates how the mechanisms can be used.
 
-The example is of a package that logs the failures of tasks due to
-unhandled exceptions. It also releases a guardian task if any task
-fails due to being aborted.
+The example is of a library package that logs the termination of all tasks and,
+separately, the terminations due to unhandled exceptions. It also releases
+a guardian task if any task fails due to being aborted. At the end of
+the program (when the environment task wishes to terminate) the logged
+information is output. This example assumes no tasks are declared within
+library units (or that elaboration control is used to make sure the
+code of the package body is executed before any library tasks start
+executing).
 
 with Ada.Task_Identification; use Ada.Task_Identification;
 with Ada.Task_Termination; use Ada.Task_Termination;
 with Ada.Exceptions; use Ada.Exceptions;
 package Termination_Logging is -- library package
   protected Logger is
-    entry Guardian;
-    procedure Log_Non_Normal_Termination (
-      Id: Task_Id; X: Exception_Occurrence);
-    procedure Note_Abnormal_Termination(Id : Task_Id);
+    entry Guardian_Control;
+    procedure Log_Termination(C : Cause;
+      Id: Task_Id; X: Exception_Occurrence := Null_Id);
+    procedure Output(C : Cause;
+      Id: Task_Id; X: Exception_Occurrence := Null_Id);
   private
     Abort_Occurrence : Boolean := False;
+    Finished : Natural := 0;
+    Exception_Finished : Natural := 0;
   end Logger;
+  task Guardian; -- calls Logger.Guardian_Control
 end Termination_Logging;
 
 package body Termination_Logging is
-
-  Old_Handler1 : Protected_Termination_Handler;
-  Old_Handler2 : Protected_Exceptional_Termination_Handler;
-
   protected body Logger is
-    entry Guardian when Abort_Occurrence is
+    entry Guardian_Control when Abort_Occurrence is
     begin
       Abort_Occurrence := False;
-    end Guardian;
-    procedure Log_Non_Normal_Termination (
-      Id: Task_Id; X: Exception_Occurrence) is
+    end Guardian_Control;
+    procedure Log_Termination (C : Cause;
+      Id: Task_Id; X: Exception_Occurrence := Null_Id) is
     begin
-      -- write out error message to operator terminal
-      -- log event to file
-    end Log_Non_Normal_Termination;
-    procedure Note_Abnormal_Termination(Id : Task_Id) is
+      Finished := Finished + 1;
+      if Cause = Unhandled_Exception then
+        Exception_Finished := Exception_Finished + 1;
+      elsif Cause = Abnormal then
+        Abort_Occurrence := True;
+      end if;
+    end Log_Termination;
+    procedure Output(C : Cause;
+      Id: Task_Id; X: Exception_Occurrence := Null_Id) is
     begin
-      Abort_Occurrence := True;
-    end Note_Abnormal_Termination;
+      -- print out the values of Finished and Exception_Finished
+    end Output;
+    task body Guardian is ...
+    Temp : Handler;
   end Logger;
 begin
-  Set_Unhandled_Exception_Handler
-      (Logger.Log_Non_Normal_Termination'Access,Old_Handler2);
-  Set_Abnormal_Termination_Handler
-      (Logger.Note_Abnormal_Termination'Access,Old_Handler1);
-  -- Old_Handler1 and Old_Handler2 should both be null
+  Set_Default_Handler(Logger.Log_Termination'Access);
+  Set_Handler(Current_Task, Logger.Output'Access, Temp);
 end Termination_Logging;
 
 !discussion

Questions? Ask the ACAA Technical Agent