CVS difference for ais/ai-00266.txt

Differences between 1.3 and version 1.4
Log of other versions for file ais/ai-00266.txt

--- ais/ai-00266.txt	2002/02/07 04:56:42	1.3
+++ ais/ai-00266.txt	2002/03/12 01:14:42	1.4
@@ -1,4 +1,4 @@
-!standard D.2.2 (5)                                02-02-05  AI95-00266/03
+!standard D.2.2 (5)                                02-03-07  AI95-00266/04
 !standard D.7 (00)
 !class amendment 01-05-10
 !status work item 01-05-10
@@ -12,14 +12,18 @@
 A mechanism is proposed for associating a task group object with a task.
 The task group object receives notification when the task is about to
 terminate. If a task terminates due to an unhandled exception,
-the exception occurrence is passed to the group. A task inherits
-the task group of its master at the time of creation, but the
-task group may be changed during the task's lifetime.
+the exception occurrence is passed to the group. By default,
+when a new task is created, the task group of its master becomes
+its task group. However, a master may locally specify a different
+"creation" group for its subtasks.
 
+A default task group may be specified to handle termination for tasks with
+no task group of their own.
+
 !problem
 
 In Ada 95, a task propagating an exception will silently be terminated.
-This is a significant hazard in high integrity systems.
+This can be a significant hazard in high integrity systems.
 
 !proposal
 
@@ -66,28 +70,22 @@
               access all Root_Task_Group'Class;
                 -- Reference to task group object
 
-            procedure Specify_Task_Group(
-              New_Group : in Task_Group_Access;
-              Old_Group : out Task_Group_Access;
-              ID : in Task_Identification.Task_ID :=
-                Task_Identification.Current_Task);
-                -- Specify the task group for the identified task.
-                -- Its current task group is returned in Old_Group.
-
-            function Current_Task_Group(
-              ID : in Task_Identification.Task_ID :=
-                Task_Identification.Current_Task) return Task_Group_Access;
-                  -- Return the current task group of the identified task.
-                  -- If this returns null at the time of termination, then
-                  -- the current default task group (see below) will be
-                  -- notified of termination.
+            function Current_Task_Group return Task_Group_Access;
+                  -- Return the task group of the current task.
+                  -- This returns null if the current task has no
+		  -- associated task group.  When a task with no task
+                  -- group terminates, the current default task
+		  -- group (see below) will be notified of termination.
+		  -- Note that the access value returned may designate
+		  -- a local task group, and hence this value should
+		  -- not be stored in a long-lived variable.
 
 
             procedure Specify_Default_Task_Group(
               New_Default_Group : in Task_Group_Access;
               Old_Default_Group : out Task_Group_Access);
                 -- Specify the task group to receive notifications
-                -- from tasks that terminate when they have a null task group.
+                -- of termination of tasks with no task group of their own.
                 -- The current "default" task group is returned in
                 -- Old_Default_Group, and is initially null.
 
@@ -95,41 +93,57 @@
                 -- Return the current default task group
 
 
-            type Local_Task_Group(
+            type Local_Task_Creation_Group(
               Group : access Root_Task_Group'Class) is
                 new Ada.Finalization.Limited_Controlled with private;
                   -- Declaring an object of this type has the effect
-                  -- of establishing a local task group for current task;
-                  -- Upon finalization, the original task group is restored.
+                  -- of establishing for the lifetime of the object
+		  -- a local task creation group for subtasks and
+		  -- for access types that designate tasks.
+		  -- The innermost local task creation group determines
+		  -- the task group when a subtask is created or
+		  -- an access type is elaborated.
+		  -- If no local task creation group has been established,
+		  -- the task's own group is used for its subtasks and
+		  -- access types.
+
+	    function Current_Task_Creation_Group return Task_Group_Access;
+		-- Return the current task creation group.
+		-- This is the task group established by the innermost
+		-- declaration of a Local_Task_Creation_Group, or the
+		-- current task's own group, if no local task creation
+		-- group has been established.
+		-- Returns null if the current task has
+		-- no task group and no local task creation group has
+		-- been established.
+		-- Note that the access value returned may designate
+		-- a local task group, and hence this value should
+		-- not be stored in a long-lived variable.
 
         private
             -- Not specified by the language
         end Ada.Task_Groups;
-
-Upon termination, the task group for a task is notified.
-The task group for a task is determined as follows:
-
-   a) The task group for the environment task is initially null;
-
-   b) The task group for a task created by a declaration
-      is set to that of its master task at the time of creation;
 
-   c) The task group for a task created by an allocator is set
-      to the group of its master task at the time of the elaboration
-      of the ultimate ancestor of the access type.
+When a task is created, its task group is determined by the
+"task creation group" associated with either its creator, if created by a
+declaration, or with its access type, if created by an allocator.
+The environment task has no associated task group, though it
+may establish a task creation group for its subtasks.
+
+Immediately prior to task termination, the task group, if any, of the
+terminating task is notified.  If the task has no task group, then
+the default task group at the time of termination, if any, is notified.
+
+The task creation group for a task starts out as the same as
+the task's own group, if any. As the task proceeds, a local
+task creation group may be established, by declaring a limited
+controlled object of the type "Local_Task_Creation_Group." When
+the Local_Task_Creation_Group is finalized, the task creation group
+is restored to its value at the time the local group was established.
+The task creation group for an access type is determined by
+the task creation group in effect when the access type declaration
+is elaborated.
 
-   d) The task group for a task can be set (or reset) by a call on
-      Specify_Task_Group identifying the task, or (for the current
-      task) by elaborating or finalizing an object of type Local_Task_Group.
-
-   e) Upon termination, if the task group is still null, then
-      the current "default" task group is used, as specified by the most
-      recent call on "Specify_Default_Task_Group."
-
-In other words, a task typically inherits the task group of its master upon
-creation, can have its group (re)set explicitly during its lifetime, and
-defaults to the "default task group" upon termination.
-
 Notifying a task group of (impending) termination consists of calling the
 appropriate primitive operation of the task group, as determined by how the
 task terminates.  If the task completes due to an abort statement, the Aborted
@@ -148,38 +162,33 @@
 "sibling" tasks are activated prior to Never_Activated being called.
 
 The result of calling Current_Task while executing Never_Activated will
-identify the activator, and the Terminated attribute of the task will be True.
-For the other three operations, the result of calling Current_Task while
-executing one of the task-group operations identifies the task about to
-terminate, and the Terminated attribute of the task will be False.
-In either case, the Callable attribute of the task will be False.
+identify the activator. While executing the Normal_Termination and
+Unhandled_Exception operations, the result of calling Current_Task
+identifies the task about to terminate. It is not specified what is
+returned by Current_Task within the Aborted operation.
 
 When Unhandled_Exception, Aborted, or Normal_Termination are called,
-task attributes created by an (active) instantiation of the
+the Terminated attribute of the terminating task will be False.
+This means that task attributes created by an (active) instantiation of the
 Ada.Task_Attributes package have not yet been finalized, allowing these
 operations to read information from the attributes.
-Inside Never_Activated, the task attributes are not available.
+When Never_Activated is called, the Terminated attribute of the task will
+be True, and the task attributes are not available.
+When any of these operations is called, the Callable attribute of
+the terminating task will be False.
 
 Note that concurrent calls on task-group operations are possible due to
 concurrent termination of tasks. Hence, these operations should be implemented
 in a reentrant manner.
 
-To support local scopes where a distinct task group is to be used,
-we have provided a limited controlled type, called "Local_Task_Group,"
-whose objects establish a specified task group when elaborated, and restore
-the old task group when finalized.  We provide this mechanism because
-it is safer than explicitly calling Specify_Task_Group before and after the
-scope, as it works even if the local scope propagates an exception
-or is aborted, and works safely with stack-allocated task groups.
-
-Note that Local_Task_Group may also be used in a library-level
-package to set the task group for library-level tasks.  The task
-group setting will persist until it is overridden by some subsequent
-elaboration of a Local_Task_Group object, or an explicit
-call on Specify_Task_Group for the environment task.  Hence, if this
-approach is used to manage library level tasks, such a Local_Task_Group
-object should appear at the beginning of every package spec or body
-that declares tasks.
+Note that Local_Task_Creation_Group may also be used in a library-level
+package to set the task creation group for library-level tasks.  The task
+creation group setting will persist until it is overridden by some subsequent
+elaboration of a Local_Task_Creation_Group object.  Hence, if this
+approach is used to manage library level tasks, such a
+Local_Task_Creation_Group object should appear at the beginning of
+every package spec or body that declares tasks or access types
+that designate tasks.
 
 !wording
 
@@ -195,57 +204,60 @@
 We have proposed a technique that is reminiscent of what Java does, in
 that it establishes a separate abstraction, called a task group ("thread
 group" in Java) which receives notification of task termination.
-However, this proposal allows a task to change its task group
-after activation.  A task inherits the task group of its master
-task whenever its master task's group is non-null and the task's
-group is null.
-
-This proposal allows each task to have its own task group, but also
-allows tasks to inherit the task group from its master task upon
-creation.  This gives a combination of fine control when needed,
+By default, a task inherits the task group its master task.  However,
+the master may establish a "task creation group" to change what
+task group is used for its subtasks.
+
+This proposal allows each scope to set up its own local task creation
+group, but by default allows tasks to inherit the task group from its master
+task upon creation. This gives a combination of fine control when needed,
 along with the convenience of inheritance otherwise.
 
-We only inherit the task group from the master at the point of
-creation, so there is less chance of a task outliving its task group.
-For a task created by an allocator, we use the task group the master
-had at the time the access type was elaborated, again, to minimize
-the chance of having the task outlive its task group.
-
-We allow a task to change its task group during execution so
-that an inner scope can establish a local task group,
-wait for all local tasks to terminate, and then restore the old
-task group.  The Local_Task_Group controlled type provides this
-capability in a way that minimizes the chance of dangling references.
+We ensure that a task cannot outlive its task group because
+local task creation groups are specified using a declaration
+of a local controlled object, rather than by an explicit subprogram
+call. For a task created by an allocator, we use the task creation
+group the master had at the time the access type was elaborated,
+again, to ensure that the task cannot outlive its task group
+(barring early unchecked deallocation).
 
 We provide a default task group to allow most or all of the tasks
-in a program to share a single group, if appropriate.
+in a program to notify a single task group, if appropriate.
 
-Because task terminations can occur immediately after task activation, it is
-We considered having two task groups associated with a given
-task, one for the task itself to notify of its termination, and
-one to be the task group to be used for subtasks created that have
-this task as a master.  This would simplify things
-in one way, since the group to use for the task itself would not
-likely change during its lifetime.  However, the group to use for
-new subtasks would still need to be saved and restored around local
-scopes, and by the time the task terminated, the task's own
-group and the group for subtasks would likely end up being the
-same again.  Hence, we felt it was overall simpler to use a single group
-for both purposes.  [This decision might deserve revisiting, since
-it does introduce some possibility of dangling references as a result
-of calling Current_Task_Group on a task that has temporarily changed
-its task group to be a local task group.  Perhaps Current_Task_Group
-should not take a task ID, and Specify_Task_Group should not return
-the old group (given that the Local_Task_Group object does an
-automatic save/restore).  Alternatively, we would have two, but
-Local_Task_Group would be the only way to affect the "subtask
-creation group" while, Specify_Task_Group and Current_Task_Group
-would refer to the task's "own" group.]
+We originally did not have the notion of a task creation group,
+while instead allowing a task to change its own group while
+it executed to indirectly affect the group used for subtasks.
+This ended up having more complicated semantics, and introduced
+additional possibilities for dangling references to task groups.
+
+We originally had a Task_ID parameter in Current_Task_Group as
+a way to query the task group of any task. However, this
+introduced too many possibilities for dangling references,
+as a task might terminate immediately after the call and its
+task group might go out of scope. An attribute of a task object
+might be an alternative safer way of providing this functionality.
+By using an attribute, we could avoid the need for using an access
+value, and could instead make the attribute reference denote the
+task group itself, as a variable, analogous to the way the
+Storage_Pool attribute works. On the other hand, if you can
+name the task, then you can figure out its task group by simply
+calling Current_Task_Creation_Group immediately prior to its
+declaration, and saving the value in a local variable.
 
 We considered a mechanism using pragmas or attributes to specify the
-task group associated with a scope, but the mechanism became too heavy.
-The Local_Task_Group controlled type provides much of the same
-capability without having to define pragmas or attributes.
+task creation group associated with a scope, but the mechanism became too
+heavy. The Local_Task_Creation_Group controlled type provides much of the
+same capability without having to define pragmas or attributes.
+On the other hand, the semantics have been simplified a bit since the
+original proposal, and a pragma equivalent to the Local_Task_Creation_Group
+declaration might be easier to define now. It would also have the
+side benefit that it could deal with library-level tasks somewhat
+more cleanly, as the pragma's effect could be limited to the tasks
+of a single library package, without "spilling over" to library packages
+that are elaborated immediately after the package.  But this would
+not be a pragma that could safely be ignored, as it has a significant
+semantic effect over subsequent calls on functions like
+Current_Task_Creation_Group.
 
 !example
 
@@ -268,8 +280,8 @@
     Grp : aliased MTG.My_Task_Group;  -- Local task group object
   begin
     declare
-      -- Establish local task group
-      LTG : Task_Groups.Local_Task_Group(Grp'Access);
+      -- Establish local task creation group
+      LTG : Task_Groups.Local_Task_Creation_Group(Grp'Access);
 
       -- Declare some local tasks
       task Local_Task1 is ...
@@ -278,7 +290,7 @@
       ... -- if Local_Task1 or Local_Task2 dies due to an unhandled excep
           -- will call Unhandled_Exception(Grp, ...)
 
-    end; -- old task group restored implicitly at this point
+    end; -- old task creation group restored implicitly at this point
 
     if MTG.Num_Unhandled(Grp'Access) > 0 then
         ... -- we got problems, report them
@@ -292,8 +304,13 @@
 
 !appendix
 
-[Editor's note: This originally was part of the Ravenscar proposal,
-see AI-249.]
+[Editor's note: This originally was part of the Ravenscar proposal.
+However, Ravenscar needed a simpler semantics, and the No_Task_Termination
+restriction was defined to encapuslate the Ravenscar requirements.
+
+At about the same time, the Exception Workshop at the 2001 Ada Europe meeting
+identified a need for detection of task termination. This proposal was then
+enhanced to meet those requirements.]
 
 ****************************************************************
 
@@ -330,5 +347,23 @@
 would consider this proposal unnecessary without further justification. I'd
 also suggest that the semantics be defined in terms of this sort of code if
 possible (it would make the proposal look "simpler", which is always good).
+
+****************************************************************
+
+From: Randy Brukardt
+Date: Friday, March  8, 2002, 10:41 PM.
+
+> Here is an update to AI 266 on task termination.  I believe
+> it incorporates most of the discussion from Cupertino.
+
+Having read through my notes and the AI, I don't think it has added the
+"Task_Created" (or whatever) operation that is mentioned in the notes
+several times.
+
+There also is a need for a No_Task_Group restriction.
+
+There is some discussion of allocating a task group and it being a bounded
+error. I don't know what this means off hand, so I can't tell if you've
+handled it.
 
 ****************************************************************

Questions? Ask the ACAA Technical Agent