CVS difference for ais/ai-00237.txt

Differences between 1.1 and version 1.2
Log of other versions for file ais/ai-00237.txt

--- ais/ai-00237.txt	2000/05/17 20:49:07	1.1
+++ ais/ai-00237.txt	2000/06/01 03:31:50	1.2
@@ -1,5 +1,5 @@
-!standard 03.10.02  (02)                               00-05-16  AI95-00237/00
-!class confirmation 00-05-16
+!standard C.07.02  (17)                               00-05-31  AI95-00237/01
+!class binding interpretation 00-05-31
 !status received 00-05-16
 !priority Low
 !difficulty Medium
@@ -7,6 +7,10 @@
 
 !summary
 
+The master of task attributes is the master of the instantiation of
+Ada.Task_Attributes that creates them. Task attributes can be finalized
+at any point after their task is terminated and no later than the completion
+of the master of the instantiation of Ada.Task_Attributes that created them.
 
 !question
 
@@ -15,18 +19,101 @@
 "When a task terminates, the implementation shall finalize all attributes
 of the task, and reclaim any other storage associated with the attributes."
 
-Does this mean *after* a task terminates, or at some time in the near
-vicinity?  And what behavior is allowed if this termination occurs
-concurrently with the interrogation of attributes of the task?
+Does this mean *after* a task terminates? (Yes.) Can the termination occur
+concurrently with the interrogation of attributes of the task? (No.)
 
+This wording also appears to allow an attribute to outlive its type. Is
+this intended? (No.)
 
-!response
+!recommendation
 
+(See summary.)
+
+!wording
+
+Add the following after C.7.2(13):
+   When the master of an instantiation of Ada.Task_Attributes is finalized,
+   the associated attribute for all tasks is finalized.
+
+Delete C.7.2(17).
+
+Add the following after C.7.2(29):
+   When a task terminates, an implementation may finalize all attributes of
+   the task, and reclaim any other storage associated with the attributes.
+
+!discussion
+
+Although it is not clear from the RM, it is not possible in general for a
+task to finalize its own attributes. That occurs because a task that is never
+activated may have attributes that require finalization.
+
+However, this begs the question: if a task owning attributes cannot finalize
+them, what task does? One way to attempt to answer the question is to determine
+the master of the attributes. (After all, for ordinary objects, it is the
+master that determines when they are finalized.) However, the RM never
+addresses this at all.
+
+It is clear that the task attributes should not exist any longer than the
+instantiation that created them. If they do exist past that point, there is the
+risk that their type is also no longer accessible, and that the finalization
+may depend on entities that no longer exist. Therefore, we declare that the
+master of the instantiation is the master of the task attributes.
+
+This gives a clear point by which the finalization of attributes must have
+completed: the completion of the master which contains the instantation.
+Once we have this clear point, we no longer need the (now) conflicting rule
+that says that the attributes are finalized when their task terminates.
+Moreover, this rule complicates implementation of task attributes, requiring
+an interaction between the attributes package and the task supervisor upon
+task termination. This can be difficult to accomplish when Ada tasking is
+built on top of an existing operating systems threading mechanisms.
+
+Therefore, we convert this rule to an implementation permission, allowing
+finalization at any point after a task terminates. We leave it as an
+implementation permission (rather than deleting it outright) for two reasons:
+   * So that existing implementation need not changed;
+   * So that attributes can be implemented as a property of a task (say, as
+     space in a task control block [TCB]). In order to support that, we have
+     to be able to finalize attributes when task data structures are freed.
+
+It is important that attributes are not finalized before task termination,
+because they can be accessed until T'Terminated becomes True. We do not want
+to be able to access finalized task attributes.
+
+
+!corrigendum  C.7.2(13)
+
+@dinsa
+For all the operations declared in this package, Tasking_Error is raised if
+the task identified by T is terminated. Program_Error is raised if the value
+of T is Null_Task_ID.
+@dinst
+When the master of an instantiation of Ada.Task_Attributes is finalized,
+the associated attribute for all tasks is finalized.
+
+!corrigendum  C.7.2(17)
+
+@ddel
+When a task terminates, an implementation shall finalize all attributes of
+the task, and reclaim any other storage associated with the attributes.
+
+!corrigendum  C.7.2(29)
+
+@dinsa
+An implementation is allowed to place restrictions on the maximum number of
+attribute a task may have, the maximum size of each attribut, and the total
+storage size allocated for all attributes of a task.
+@dinst
+When a task terminates, an implementation may finalize all attributes of
+the task, and reclaim any other storage associated with the attributes.
 
 !ACATS test
 
-This issue is not testable unless a deterministic semantics is required.
-[I hope that doesn't happen - ED.]
+It would be possible to create a test to insure that task attributes are
+finalized at some point between the termination of the task and the leaving
+of the instantation's master, but such a test would not add much value to
+CXC7003.A (which already tests finalization of attributes, but not this
+specific case).
 
 !appendix
 
@@ -732,6 +819,1138 @@
 marking the task as terminated obviates the need to further specify the
 order of attribute finalization, as Mike pointed out, which simplifies
 implementation.
+
+*************************************************************
+
+From: Tucker Taft
+Sent: Wednesday, May 17, 2000 9:57 PM
+
+Randy Brukardt wrote:
+> Replace C.7.2(13) by:
+>
+> For all of the operations defined in this package, Tasking_Error is raised
+> if the finalization of the attribute has begun.
+
+I presume you only meant to replace the first sentence C.7.2(13)
+I would rather see :
+
+   For all of the operations defined in this package, Tasking_Error is raised if the
+   task identified by T is terminated, or the implementation has begun
+   finalization of the attribute.
+
+> Combined with C.7.2(17), this is similar to the existing rule, but it
+> eliminates worrying about whether a terminated task (as opposed to completed
+> task) can run. (Remember that objects of *all* types are finalized, not just
+> tagged types.)
+>
+> I think this has the minimal change, and avoids the grey area. But I'm no
+> expert in real-time programming, so I might have missed something.
+
+I think we should preserve the fact that once 'Terminated is true,
+you get Tasking_Error.  You may start getting it a bit earlier than that,
+but no later.
+
+*************************************************************
+
+From: Robert A Duff
+Sent: Thursday, May 18, 2000 10:31 AM
+
+>    For all of the operations defined in this package, Tasking_Error is raised if the
+>    task identified by T is terminated, or the implementation has begun
+>    finalization of the attribute.
+
+Don't we want to allow the implementation to raise T_E if it has started
+finalizing *some* attribute, and some other task accesses some *other*
+attribute?  Otherwise, the implementation has to keep track of which
+attributes it has finalized, individually.  It seems easier to implement
+if it can simply keep track of the fact that it has started finalizing
+the attributes.  It seems like this would not affect programs -- how can
+you write a program that cares about the difference between "we have
+started finalizing attribute X" and "we are about to start finalizing
+attribute X real soon -- as soon as we get done finalizing attribute Y"?
+Such a program would get T_E anyway, if the other task were just a
+little bit slower.
+
+Am I making sense?
+
+*************************************************************
+
+From: Michael Yoder
+Sent: Thursday, May 18, 2000 12:32 PM
+
+Ted Baker wrote:
+>I mentioned earlier that there
+>are situations where this is impossible, i.e., the task whose
+>attributes are being finalized never even activated, but we still
+>have to finalize the attribute values.
+
+I cannot find this in your earlier messages.  Could you provide a
+pointer?  If I have missed a message I'd like to read it.
+
+*************************************************************
+
+From: Jean-Pierre Rosen
+Sent: Thursday, May 18, 2000 2:35 AM
+To: Ada-Comment List
+Subject: Re: [Ada-Comment] finalization of task attributes; value of
+Current_Task
+
+> | I was surprised in this discussion that everybody talked only
+> | about *terminated* tasks.  For variables declared in the task
+> | body, finalization happens when the task is *completed*, but not
+> | yet *terminated* - see 9.3(5).
+>
+> | Is there any reason to believe that task attributes do not behave
+> | the same ? After all, they are quite like variables declared
+> | directly within the task. Admitedly, the phrasing "when the task
+> | terminates" is vague, but it would seem logical to admit this
+> | describes the termination process in 9.3(5).
+>
+> There can be a very long (maybe forever) delay between completion
+> and termination of a task.  Finalization of task attributes before
+> termination is illegal.
+>
+Of course. I just meant that:
+- during finalization, the task should be seen as completed, but not terminated.
+- finalization of task attributes should be considered part of "finalization of
+  the task body", as defined in 9.3(5).
+
+I agree that accessing the attribute after finalization has started should raise
+Tasking_Error, which is a bit earlier than when the task is terminated.
+
+(Note however that there are other places in the language where you can access a
+variable after it has been finalized, but that would be unfortunate in this
+case, since it would mean accessing released memory).
+
+*************************************************************
+
+From: Ted Baker
+Sent: Thursday, May 18, 2000 12:30 PM
+
+| As you point out in a previous message, that would require changes to
+| some implementations, in particular Apex.  Our runtime has a terminated
+| task mark itself as terminated and then finalize its attributes.  The
+| terminated flag itself is used to determine if Tasking_Error should be
+| raised on attribute reference.  Once the attributes are finalized the
+| task never runs again.  Deferring attribute finalization further would
+| require having another task do the work, which I suspect would be a
+| nontrivial change.
+
+I am not pushing for a change.  I would prefer leaving the
+language as it is.  I just wanted to point out in opposition to
+the proposal for moving finalization of attributes earlier (task
+completion) that if we are ready to break implementations and
+applications, it would be better to gain something useful for the
+user.  I think the later finalization would do that.
+
+| I wonder if the original idea of saying that the attributes are
+| finalized on task termination is just to indicate that their
+| finalization needs to come after the rest of the task body finalization,
+| that is, the finalization of objects declared in the task body,
+...
+| Finalizing the attributes after marking the
+| task as terminated obviates the need to further specify the order of
+| attribute finalization, as Mike pointed out, which simplifies
+| implementation.
+
+That is what I have always thought.  That is, the finalization
+of task attributes must happen after the finalization of all the
+objects within the task body.  In that way those finalizations
+can safely use the task attributes.
+
+| ...just to preserve LIFO ordering.
+
+I don't think LIFO fits here, since the values of the task
+attributes can be changed dynamically during the lifetime of the
+task.  Also, a new task attribute can be created after the
+creation of a task.  There is just no connection between the
+lifetimes of the attribute values and the tasks, other than it
+makes sense toe force cleanup at the end of the task to avoid
+storage leakage.
+
+*************************************************************
+
+From: Ted Baker
+Sent: Thursday, May 18, 2000 12:15 PM
+
+| We *have* to change something here, because the current situation allows
+| access to finalized attributes on some implementations. We need to at least
+| tighten up the language of this section to prevent that.
+
+I don't see any such gap.  The language currently requires that
+Tasking_Error be raised if the user attempts to access one of
+these attributes of a task that has reached the "terminated"
+state.  I think we all agree that the task is marked as
+"terminated" when it begins the termination process, so that
+during finalization the task is viewed as terminated.
+
+| But certainly your idea is at least as bad as Tucker's: it requires proxy
+| finalizations, which may not be possible on all implementations of
+| finalization. And it certainly would require most implementations to change.
+
+1) The concept of "proxy" here has no relevance, as these objects
+that are being finalized do not "belong" to any one task in the
+sense that local objects do.  In general, the attribute objects
+will have already been initialized via what you are calling a
+"proxy".  Moreover, if another task changes the value of an
+attribute, the finalization will be done by the task that changes
+the attribute value.  In general, these attributes can be
+initialized by any task and finalized by any task.
+
+2) You have no choice but to use another task in the case where the
+task was never activated.
+
+Everything I said above applys to the current semantics,
+and I can accept leaving things alone since they are not really
+broken.  I think no change is called for.
+
+On the other hand, if we are to make a change, I think the
+argument is in favor of requiring that finalization be delayed
+further, for the reasons stated in my earlier e-mail.
+
+*************************************************************
+
+From: Randy Brukardt
+Sent: Thursday, May 18, 2000 2:51 PM
+
+> I don't see any such gap.  The language currently requires that
+> Tasking_Error be raised if the user attempts to access one of
+> these attributes of a task that has reached the "terminated"
+> state.  I think we all agree that the task is marked as
+> "terminated" when it begins the termination process, so that
+> during finalization the task is viewed as terminated.
+
+WHOA! (Deja-vu:-) Apparently, your messages aren't the only ones that aren't
+being read. I certainly don't agree with the above statement - I believe that
+any model where a terminated task can execute is flawed. That is why we have the
+"completed" state - it applies to a task which has finished executing but still
+has finalization to do.
+
+Which is why I proposed rewriting C.7.2(13) to eliminate the problem. But you
+seem to have refused to even comment on it - thus we seem to have two parallel
+conversations.
+
+In any case, C.7.2(17) does not say what you stated; if there really is a
+consensus that your statement is true, then we need to rewrite C.7.2(17) to say
+so (and to provide a red flag that the Ada 'Terminated has to be carried as a
+separate flag - it would then have nothing to do with the *real* status of the
+task).
+
+> | But certainly your idea is at least as bad as Tucker's: it requires proxy
+> | finalizations, which may not be possible on all implementations of
+> | finalization. And it certainly would require most
+> implementations to change.
+>
+> 1) The concept of "proxy" here has no relevance, as these objects
+> that are being finalized do not "belong" to any one task in the
+> sense that local objects do.  In general, the attribute objects
+> will have already been initialized via what you are calling a
+> "proxy".  Moreover, if another task changes the value of an
+> attribute, the finalization will be done by the task that changes
+> the attribute value.  In general, these attributes can be
+> initialized by any task and finalized by any task.
+
+There is something very wrong with the model you explain here. The lifetime of
+the attribute has to be at least as long as the task that it is an attribute of.
+However, the task that sets the attribute may have terminated long before the
+attribute is finalized; there is no way in general for that task to finalize the
+attribute.
+
+The only possible ways to implement these things are either that they "belong"
+to the task containing the attribute (possibly requiring a proxy operation), or
+that they "belong" to a pseudo-task that surrounds the environment task. In
+either case, setting them requires a assigning them so that belong to the
+appropriate scope (possibly with some sort of proxy); they cannot remain owned
+by the caller.
+
+> 2) You have no choice but to use another task in the case where the
+> task was never activated.
+
+And since no such task is available in general, it can only be done at the
+appropriate point by launching an extra task to do it. (The task supervisor
+itself can't call user code, as that might call back into the task supervisor,
+which could deadlock or worse.)
+
+You have convinced me that it is impossible to correctly implement these things
+(at least in Janus/Ada). Or, at least that it is unbearably expensive. And all
+for a feature of very little benefit (tasks don't terminate very often in real
+Ada programs, as they usually are either library level or declared by an access
+to task at the library level). (The memory deallocation is not a problem, as it
+can occur along with deallocation of other task structures).
+
+The problem, of course, is the use of controlled types as task attributes. The
+only solution I see is prohibiting them altogether. I doubt I could get enough
+support for that in RM, but an implementation can do it with creative use of
+C.7.2(18). I recommend that to all of the implementors.
+
+(For me personally, a better solution would be to burn all of my Ada books and
+go bag groceries -- I'd make more money that way...)
+
+				Randy.
+
+
+*************************************************************
+
+From: Michael Yoder
+Sent: Thursday, May 18, 2000 1:13 PM
+
+At 11:31 AM 5/18/00 -0400, you wrote:
+> >    For all of the operations defined in this package, Tasking_Error is
+> raised if the
+> >    task identified by T is terminated, or the implementation has begun
+> >    finalization of the attribute.
+>
+>Don't we want to allow the implementation to raise T_E if it has started
+>finalizing *some* attribute, and some other task accesses some *other*
+>attribute?  Otherwise, the implementation has to keep track of which
+>attributes it has finalized, individually.  It seems easier to implement
+>if it can simply keep track of the fact that it has started finalizing
+>the attributes.  It seems like this would not affect programs -- how can
+>you write a program that cares about the difference between "we have
+>started finalizing attribute X" and "we are about to start finalizing
+>attribute X real soon -- as soon as we get done finalizing attribute Y"?
+>Such a program would get T_E anyway, if the other task were just a
+>little bit slower.
+
+Yes, but an implementation that went down this path wouldn't need the new
+flexibility.  (This is equivalent to what Randy called bogus termination
+earlier.)  It could rename the property "attribute finalization started" to
+"terminated," and rename "terminated" to 'truly and sincerely terminated"
+when the RTL internally used the property that all of a task's data
+structures were gone.
+
+*************************************************************
+
+From: Ted Baker
+Sent: Thursday, May 18, 2000 4:22 PM
+
+>WHOA!!!  (Isn't anybody reading?)  I mentioned earlier that there
+>are situations where this is impossible, i.e., the task whose
+>attributes are being finalized never even activated, but we still
+>have to finalize the attribute values.
+
+| I cannot find this in your earlier messages.  Could you provide a
+| pointer?  If I have missed a message I'd like to read it.
+
+Sorry.  Since I don't see the echo-back copy of the message in my
+mail compendium, it may have one of those messages I occasionally
+lose when somebody interrupts me and my system goes down before I
+finish composing and hit the send key, or maybe it was one of
+those cases where I decided I was over-elaborating the point and
+decided to delete part of the message before hitting the send key.
+Here is the point:
+
+There is a period of time between creation of a task and its
+activation, during which the task object exists but there is
+no associated active thread of control.  If an exception is
+raised in the creator/activator task the newly created task
+will never be activated.  However, it may have task attributes
+and the attributes still need to be finalized.  This cannot be
+done by the task itself, since that task was never activated
+and has no thread of control.
+
+Hence, it is absolutely necessary that there be a provision for
+what has been (I believe incorrectly, but memorably) called
+"proxy" finalization of the attributes.
+
+Given this necessity, there is no benefit to an implemenation in
+insisting in other cases that the finalization of attribute values
+ever be done by the task with which they are associated.
+
+| 17   When a task terminates, the implementation shall finalize all attributes
+| of the task, and reclaim any other storage associated with the attributes.
+
+I think I can speak with some authority on this issue, since the
+only reason we have this clause is that I argued for it back when
+I was on the 9X MRT.  Tucker and Offer did not want it originally,
+until I convinced them that users need this capability to prevent
+storage leakage and clean up dangling references.
+
+The word "when" is used in the above clause in the sense it is
+commonly used in sentence such "When you finish eating, please
+wash the dishes."
+
+The clause does not say the task shall finalize the attributes.
+It says "the implementation".  That was intentional, because there
+are situations where the task has never started execution, as
+mentioned above.
+
+The finalization of attributes is connected in this sentence with
+the reclamation of storage.  That is intentional, and is
+consistent with the treatment of unchecked deallocation of
+objects, which also requires finalization of attributes.
+
+The finalization of the task attributes would normally be done by
+whatever thread of control relaims the storage of the task.
+
+*************************************************************
+
+From: Michael Yoder
+Sent: Thursday, May 18, 2000 3:53 PM
+To: Ada-Comment List
+Subject: Re: [Ada-Comment] finalization of task attributes; value of
+Current_Task
+
+Randy Brukardt wrote:
+
+>The only possible ways to implement these things are either that they
+>"belong" to the task containing the attribute (possibly requiring a proxy
+>operation), or that they "belong" to a pseudo-task that surrounds the
+>environment task. In either case, setting them requires a assigning them so
+>that belong to the appropriate scope (possibly with some sort of proxy);
+>they cannot remain owned by the caller.
+
+Actually, you can have them belong to the environment task itself.  This
+seems to raise the question "Who finalizes the environment task's
+attributes?".  However, if you examine the process closely, you find that
+the attributes get finalized as their scopes are exited, so that when the
+time comes to finalize the environment task's attributes after its
+termination, the number left to finalize must be zero.  So you escape by a
+whisker.
+
+*************************************************************
+
+From: Ted Baker
+Sent: Thursday, May 18, 2000 3:53 PM
+To: ada-comment@ada-auth.org
+Subject: Re: [Ada-Comment] finalization of task attributes; value of
+Current_Task
+
+| Don't we want to allow the implementation to raise T_E if it has started
+| finalizing *some* attribute, and some other task accesses some *other*
+| attribute?  Otherwise, the implementation has to keep track of which
+| attributes it has finalized, individually.
+
+That is what the current semantics say, i.e.,
+you mark the task as Terminated at some point, and start finalization
+after that point.  The task attribute operations just check
+raise Tasking error if T'Terminated is true.
+It is all very simple.
+
+WHAT IS THE PROBLEM PEOPLE ARE TRYING TO SOLVE HERE?
+
+This whole thread seems to be talking about making unnecessary
+languages changes.  I have not yet seen any problem that requires
+a language change.
+
+*************************************************************
+
+From: Randy Brukardt
+Sent: Thursday, May 18, 2000 6:10 PM
+
+Mike Yoder wrote:
+
+> Actually, you can have them belong to the environment task itself.  This
+> seems to raise the question "Who finalizes the environment task's
+> attributes?".  However, if you examine the process closely, you find that
+> the attributes get finalized as their scopes are exited, so that when the
+> time comes to finalize the environment task's attributes after its
+> termination, the number left to finalize must be zero.  So you escape by a
+> whisker.
+
+You are either being unclear here, or one of us completely misunderstands
+the model, because the attributes certainly survive their (original) scopes
+exiting.
+Set_Value clearly is an assignment (including the call to Adjust)
+[C.7.2(11)]. The original scope of the item is irrelevant. This assignment
+would presumably arrange to have the item in the appropriate scope. (Ted
+seems to have this misunderstanding.)
+
+But in that case, the attributes of the environment task certainly still
+exist when it terminates - because nothing else could finalize them. Whether
+it matters (or whether they simply can be finalized "early"), is an open
+question.
+
+In Janus/Ada, at least, the environment task is special (in order that
+programs that don't use any tasking can avoid the substantial overhead of
+the task supervisor), and when it's finalization is complete, the only
+possible thing to do is an immediate exit of the program. It's not practical
+to change that.
+
+Doing finalization of these entities is clearly a problem. We're using a
+special finalization item tag to do this when the task terminates, but as
+Ted points out, that doesn't work for unactivated tasks.
+
+Our task supervisor cannot call user code (it's not reentrant when a context
+switch is required, as there is only a single save area); it has to use
+another task to finalize things. And forcing a task to finalize something is
+a one-way trip: it's not possible to return to what it was previously doing
+(because the saved registers, etc, would be killed if it swapped out). So
+the only way to handle unactivated tasks would be a spawn a task
+specifically to call the finalize.
+
+I find this whole thing quite dubious, because in practice, Ada tasks don't
+terminate until the program does. The only time I've seen tasks terminate
+before the end of the program is in validation tests and in a couple of test
+programs I constructed to make sure that the resources are recovered at that
+point. But end users tend to call and complain that the resources (mainly
+memory) aren't recovered when the task is completed: which isn't possible in
+Ada 95 because the task has to run to execute finalizations. They mistake
+completion for termination. That distinction is confusing enough (and that
+is why I object to any semantics that implies that terminated tasks can run,
+even for a short period). Anyway, when these things are finalized is
+unlikely to matter to most programs, simply because all of the tasks
+terminate along with the application. Similarly storage leakage of
+attributes is nearly irrelevant.
+
+It is interesting to note that the only reason that this package even has
+*anything* to do with the task supervisor is C.7.2(17). Otherwise, it is
+simple stand-alone library package.
+
+Perhaps something on the line of Ted's idea is right: change C.7.2(17) into
+an implementation permission. Then there would be no requirement to finalize
+these things at an particular point, and the problems would go away -- they
+could be finalized as late as the ending of the application. As it is, the
+only viable alternative for Janus/Ada is to completely prohibit the use of
+controlled types in Ada.Task_Attributes -- because the work involved in
+getting this to work right far exceeds any possible benefit.
+
+*************************************************************
+
+From: Randy Brukardt
+Sent: Thursday, May 18, 2000 6:29 PM
+
+> WHAT IS THE PROBLEM PEOPLE ARE TRYING TO SOLVE HERE?
+
+I think that everybody but you thought it was possible, even expected, for
+the task itself to finalize the attributes. Thus all of the discussion about
+when the 'Terminated flag.
+
+You are clearly right about that, but I think it is too expensive to force
+implementors to do, and this implementor, at least, has no intention of
+spending a couple of weeks to redo all of our task supervisor to handle a
+case that hardly ever appears in practice. And based on our experience with
+environment-level finalization in Claw, compiler writers have a lot more
+important things to get right before worrying about this one.
+
+If it was up to me, I'd simply repeal C.7.2(17), since it no longer serves
+any real purpose (C.7.2(13) and the generic instantiation rules seem to
+prevent all of the problem cases.) But banning controlled types as
+attributes works as well. I suspect that any attempt to test this would have
+the effect of causing a lot of compilers to do exactly that.
+
+For what it's worth, Janus/Ada has never made any attempt to implement
+C.7.2(17), and based on this discussion, its clear it should never try to do
+so.
+
+*************************************************************
+
+From: Tucker Taft
+Sent: Thursday, May 18, 2000 5:57 PM
+
+Ted Baker wrote:
+> WHAT IS THE PROBLEM PEOPLE ARE TRYING TO SOLVE HERE?
+
+The problem is that the RM is not clear what is the value of 'Terminated
+while attribute finalization is occurring.  You think it is clear that
+'Terminate is true before finalization starts, and I agree that solves
+Mike's problem.  However, Randy indicates that making 'Terminated appear true
+before finalization of attributes is finished is a hardship in his compiler.
+
+So one solution is to allow Tasking_Error to be raised either when the
+task is terminated, or when it has reached the stage of finalizing task
+attributes, whichever comes first.  The other solution is to require
+that 'Terminated be true before finalization starts.  I believe Randy
+would prefer the first solution.  You seem to believe that the latter
+is clearly the intent of the RM, but at least Randy doesn't agree.
+
+*************************************************************
+
+From: Ted Baker
+Sent: Friday, May 19, 2000 5:42 PM
+To: ada-comment@ada-auth.org
+Subject: Re: [Ada-Comment] finalization of task attributes; value of
+Current_Task
+
+I did not get that from his comments, but I don't see leaving this
+detail unspecified as being a problem.
+
+*************************************************************
+
+From: Tucker Taft
+Sent: Thursday, May 18, 2000 8:56 PM
+
+Randy Brukardt wrote:
+>
+> Mike Yoder wrote:
+>
+> > Actually, you can have them belong to the environment task itself.  This
+> > seems to raise the question "Who finalizes the environment task's
+> > attributes?".  However, if you examine the process closely, you find that
+> > the attributes get finalized as their scopes are exited, so that when the
+> > time comes to finalize the environment task's attributes after its
+> > termination, the number left to finalize must be zero.  So you escape by a
+> > whisker.
+>
+> You are either being unclear here, or one of us completely misunderstands
+> the model, because the attributes certainly survive their (original) scopes
+> exiting.
+> ...
+
+When the scope of an instantiation of Ada.Task_Attributes ends, it makes sense
+to finalize the corresponding attribute in all tasks. This is particularly
+important if the instantiation is not library level, because the attribute type
+might also be going away soon after the instantiation goes away. So I believe
+what Mike is saying is that by the time the environment task terminates, all of
+the instantiations of Ada.Task_Attributes have been finalized, and hence there
+are no attributes left on it.
+
+It is unfortunate that the RM doesn't talk explicitly about what happens when
+an instantiation of Ada.Task_Attributes is finalized.  Our implementation
+happens to follow the same approach as Mike suggests, namely finalizing the
+attribute in all tasks when the instantiation is finalized, but it is hard to
+find a requirement for that in the RM (other than the usual underlying
+reasonableness requirement that Robert Dewar mentions now and then ;-).
+
+*************************************************************
+
+From: Michael Yoder
+Sent: Friday, May 19, 2000 10:39 AM
+
+Ted Baker wrote:
+>WHAT IS THE PROBLEM PEOPLE ARE TRYING TO SOLVE HERE?
+
+C.7.2(17) says "When a task terminates,...".  This is ambiguous; if it had
+said "After a task terminates" there would be no ambiguity.  I phrased my
+original query conditionally exactly because I *feared* the ambiguity was
+intentional, and *hoped* that pointing out the consequences would lead to
+tightening the language (or interpreting it tightly).
+
+Here is a trial balloon.  Randy could clearly use C.7.2(29) to restrict
+attributes to those too small to contain controlled components or task
+components.  It seems reasonable that any restriction looser than that
+should be permitted while still claiming to implement Annex C.  So, for
+example, he could say that his implementation forbids attributes requiring
+non-null finalization.  Then there would be no obstacle to taking the
+strict interpretation, unless there are others here with lurking
+objections, as it were.
+
+My preference would be to change the word "when" to "after" in C.7.2(17).
+
+*************************************************************
+
+From: Ted Baker
+Sent: Friday, May 19, 2000 5:54 PM
+
+| C.7.2(17) says "When a task terminates,...".  This is ambiguous; if it had
+| said "After a task terminates" there would be no ambiguity.  I phrased my
+| original query conditionally exactly because I *feared* the ambiguity was
+| intentional, and *hoped* that pointing out the consequences would lead to
+| tightening the language (or interpreting it tightly).
+
+In my recollection, the ambiguity was intentional, and I think it
+is useful.
+
+| Here is a trial balloon.  Randy could clearly use C.7.2(29) to restrict
+| attributes to those too small to contain controlled components or task
+| components.  It seems reasonable that any restriction looser than that
+| should be permitted while still claiming to implement Annex C.  So, for
+| example, he could say that his implementation forbids attributes requiring
+| non-null finalization.  Then there would be no obstacle to taking the
+| strict interpretation, unless there are others here with lurking
+| objections, as it were.
+
+This is a reasonable approach.
+
+*************************************************************
+
+From: Michael Yoder
+Sent: Friday, May 19, 2000 9:33 AM
+
+Randy Brukardt wrote:
+>Mike Yoder wrote:
+>
+> > Actually, you can have them belong to the environment task itself.  This
+> > seems to raise the question "Who finalizes the environment task's
+> > attributes?".  However, if you examine the process closely, you find that
+> > the attributes get finalized as their scopes are exited, so that when the
+> > time comes to finalize the environment task's attributes after its
+> > termination, the number left to finalize must be zero.  So you escape by a
+> > whisker.
+>
+>You are either being unclear here, or one of us completely misunderstands
+>the model, because the attributes certainly survive their (original) scopes
+>exiting.
+
+You are right that I misunderstand the model if this is true, and upon
+reading C.7.2 I find no support for my belief, which dismays me.  My belief
+comes from this paragraph of section C.6.2 of the Ada 95 Rationale:
+
+"The generic package Task_Attributes can be instantiated locally in a scope
+deeper than the library level.  The effect of such an instantiation is to
+define a new attribute (for all tasks) for the lifetime of that
+scope.  When the scope is left, the corresponding attribute no longer
+exists and cannot be referenced anymore.  An implementation may therefore
+deallocate all such attribute objects when the scope is left."
+
+Such deallocation would presumably require that finalization be done first.
+
+Failing to allow this (indeed, failing to *require* this) would have very
+serious consequences: you could create objects whose finalization used
+variables and types that no longer existed, for example.
+
+This is certainly a turn of affairs I didn't anticipate.  :-)  I confess I
+took the above paragraph on faith without looking for explicit support in
+the LRM.
+
+*************************************************************
+
+From: Ted Baker
+Sent: Friday, May 19, 2000 5:56 PM
+
+I believe it was intended that when the scope of an instantiation
+of Task_Attributes is left, the attribute values be finalized and
+the associated storage recovered.  That is how we implemented it in
+GNARL.
+
+*************************************************************
+
+From: Randy Brukardt
+Sent: Friday, May 19, 2000 1:32 PM
+
+Well, I doubt that anyone would seriously argue that we don't want to require
+finalization at this point. So, I think we need at add something like
+   "When the master of an instantiation of Ada.Task_Attributes is finalized,
+the associated attribute for all tasks is finalized."
+after C.7.2(13).
+
+This has the advantage of making it clear what the master for task attribute
+objects is, which makes the semantics much more deterministic. (The master
+matters, of course, for types with controlled subcomponents).
+
+I would argue that adding this rule makes C.7.2(17) unnecessary, so I would
+suggest turning it into an implementation permission (so that existing
+implementations would not have to change).
+   "When a task terminates, an implementation may finalize all attributes of
+the task, and reclaim any other storage associated with the attributes."
+
+The second change would eliminate all of my objections/problems, and would have
+very little effect on real programs (since tasks rarely terminate before the
+entire program).
+
+The need to spawn a task to finalize attributes when a task terminates is far to
+heavyweight for a feature that will be rarely used (that is, the combination of
+controlled task attributes and tasks that actually terminate). I don't think
+that the expense to every tasking program (in size, at least) and especially to
+every task that uses task attributes (even of none of them are controlled) is
+justified.
+
+*************************************************************
+
+From: Robert A Duff
+Sent: Friday, May 19, 2000 1:13 PM
+
+J-P says:
+
+> (Note however that there are other places in the language where you can
+> access a variable after it has been finalized, but that would be
+> unfortunate in this case, since it would mean accessing released
+> memory).
+
+Yes, there are other places in the language where you can reference
+finalized objects.  However, there is no place in the language where a
+task can reference an object that is simultaneously being finalized by a
+different task.  At least, there *should* be no such place, which was
+Mike's original point.
+
+*************************************************************
+
+From: Robert A Duff
+Sent: Friday, May 19, 2000 12:52 PM
+
+Mike Yoder says:
+
+> You are right that I misunderstand the model if this is true, and upon
+> reading C.6.7 I find no support for my belief, which dismays me.  My belief
+> comes from this paragraph of section C.6.2 of the Ada 95 Rationale:
+>
+> "The generic package Task_Attributes can be instantiated locally in a scope
+> deeper than the library level.  The effect of such an instantiation is to
+> define a new attribute (for all tasks) for the lifetime of that
+> scope.  When the scope is left, the corresponding attribute no longer
+> exists and cannot be referenced anymore.  An implementation may therefore
+> deallocate all such attribute objects when the scope is left."
+>
+> Such deallocation would presumably require that finalization be done first.
+>
+> Failing to allow this (indeed, failing to *require* this) would have very
+> serious consequences: you could create objects whose finalization used
+> variables and types that no longer existed, for example.
+
+Yes, that does seem like a hole.
+
+So are we saying that an attribute can be finalized at any time after
+'Terminated becomes true, and before the instantiation goes away?  In
+particular, for a library-level instantiation, all task attributes can
+be finalized just before the program is done.  In fact, this implies
+that an implementation that does the finalization *only* when the
+instantiation is finalized is correct -- the implementation can
+completely ignore task termination, and just let the attributes stay
+around until much later.
+
+If "when" means "after", then it could be "long after".
+
+That implementation would seem to make Randy happy.  True?
+
+Is this what you and Ted believe the rules should be (or what the rules
+already are, in Ted's case)?
+
+- Bob
+
+P.S. Our implementation has some problems in this area.  I'm waiting for
+this discussion to settle down before I fix them!
+
+*************************************************************
+
+From: Michael Yoder
+Sent: Friday, May 19, 2000 11:34 AM
+
+I wrote:
+...  Randy could clearly use C.7.2(29) to restrict attributes to those too
+small to contain controlled components or task components.
+
+Dummy!  Task attributes can't be limited, so task components can't occur here.
+
+*************************************************************
+
+From: Ted Baker
+Sent: Friday, May 19, 2000 1:31 PM
+
+| I agree that accessing the attribute after finalization has
+| started should raise Tasking_Error, which is a bit earlier than
+| when the task is terminated.
+
+No.  The above remark implies that termination is an instantaneous
+transition.  The task needs to marked as Terminated before the
+finalization of attributes begins.  --Ted
+
+*************************************************************
+
+From: Ted Baker
+Sent: Friday, May 19, 2000 1:34 PM
+
+| ... and rename "terminated" to 'truly and sincerely terminated"
+| when the RTL internally used the property that all of a task's data
+| structures were gone.
+
+No.  If you did this there would be no place where T'Terminated
+could ever return False.  That is because the earliest point you
+can delete the last of the task's data structures is when there
+can be no further reference to the task.
+
+Moreover, if you did this change I believe it would break lots of
+applications and guess it would break quite a few validation
+tests, since I recall quite a few of them using T'Terminated at
+points and expecting it to return False.
+
+*************************************************************
+
+From: Michael Yoder
+Sent: Friday, May 19, 2000 2:16 PM
+To: Ada-Comment List
+Subject: Re: [Ada-Comment] finalization of task attributes; value of
+Current_Task
+
+You misunderstand what I was saying.  What I said had bearing only on
+implementations that wanted to take advantage of the change being discussed
+which would allow raising Tasking_Error when an attribute's finalization
+started, this finalization being started *before* the task became terminated.
+
+Bob's suggestion was that this exception might be permitted when *any*
+attribute had started finalization.  My point was: if the implementation
+was recording this point in time for the sake of the attributes package, it
+could simply redefine when 'Terminated became true to be identical with
+that point in time.  If the RTS had previously been using the property that
+termination implied all data structures were gone, it could rename its old
+"terminated" property to be something else (e.g. finalized, or fully
+terminated, or whatever) when it needed this stronger property to hold for
+the sake of its internal algorithms.
+
+The point, then, was that such an implementation would not need the
+additional implementation flexibility, since it could by a simple
+transformation comply with the stricter requirement that 'Terminated be
+true before attribute finalization started.
+
+*************************************************************
+
+From: Michael Yoder
+Sent: Friday, May 19, 2000 3:25 PM
+
+Randy Brukardt wrote:
+>The need to spawn a task to finalize attributes when a task terminates is
+>far to heavyweight for a feature that will be rarely used (that is, the
+>combination of controlled task attributes and tasks that actually
+>terminate). I don't think that the expense to every tasking program (in
+>size, at least) and especially to every task that uses task attributes (even
+>of none of them are controlled) is justified.
+
+I think you need only one global task to get early attribute finalization
+(in your implementation).  I could tolerate the overhead of one task for
+the sake of having task attributes, but you might judge differently.
+
+I like the suggestion you and Bob have independently proposed.
+
+*************************************************************
+
+From: Ted Baker
+Sent: Friday, May 19, 2000 5:27 PM
+
+| ... any model where a terminated task can execute is flawed.
+
+You should have objected more strongly during the Ada 9X processs,
+then.  This is not something new.  It is a change that has been
+there in the language definition all along.
+
+| That is why we have the "completed" state - it applies to a task
+| which has finished executing but still has finalization to do.
+
+There are other reasons for Completed, including waiting for
+dependent tasks to terminate.  Your comment about finalization
+only applies to finalization of objects declared within the task.
+
+| Which is why I proposed rewriting C.7.2(13) to eliminate the problem. But
+| you seem to have refused to even comment on it - thus we seem to have two
+| parallel conversations.
+
+Sorry.  I saw that and did not comment on the specifics because I
+am completely oppoesed to making any change.  There is no need for
+change, and this is a case where change breaks implementations and
+user programs.  Hence.
+
+| In any case, C.7.2(17) does not say what you stated; if there really is a
+| consensus that your statement is true, then we need to rewrite C.7.2(17) to
+| say so (and to provide a red flag that the Ada 'Terminated has to be carried
+| as a separate flag - it would then have nothing to do with the *real* status
+| of the task).
+
+No. C.7.2(17) does say what I stated.
+
+| 17 When a task terminates, the implementation shall finalize all
+| attributes of the task, and reclaim any other storage associated
+| with the attributes.
+
+Interpreting this as ambiguously as it was intended, i.e., to
+cover the range of meanings from "when a person finishes eating
+the person shall wash up the dishes" through "when a person eats
+the person shall not talk with his mouth full", this means that
+finalization should be done some time during or after termination.
+
+Interpreting this as ambiguously as it was intended, the implementation
+may cause the task itself to do the finalization, or do it via some
+other thread of control, as appropriate.
+
+Interpreting this in the context of stroage reclamation, as it was
+intended, the finalization of attributes should be done as part
+of the deallocation of the storage associated with the task
+implementation.
+
+| There is something very wrong with the model you explain here. The lifetime
+| of the attribute has to be at least as long as the task that it is an
+| attribute of. However, the task that sets the attribute may have terminated
+| long before the attribute is finalized; there is no way in general for that
+| task to finalize the attribute.
+
+I did not say the task that created the attribute needs to
+finalize it.  I just argued that there is no need for a special
+connection between a given task and who finalizes the attributes
+associated with the given task for the last time.
+
+| The only possible ways to implement these things are either that they
+| "belong" to the task containing the attribute (possibly requiring a proxy
+| operation), or that they "belong" to a pseudo-task that surrounds the
+| environment task. In either case, setting them requires a assigning them so
+| that belong to the appropriate scope (possibly with some sort of proxy);
+| they cannot remain owned by the caller.
+
+There is no need for the attributes to be "owned" by any
+particular task.
+
+The usual concept of "scope" does not apply to task attributes in
+the sense of objects that are declared within a master.  The
+storage for an attribute value may be allocated (and initialized)
+when (a) an instance of the Task_Attributes package is elaborated
+at run time -- at which point the elaboration of the package
+creates default attribute values for all existing tasks, (b) a new
+task is created -- at which point the creation of the task creates
+defacult values for the existing attributes of the task, (c) a
+call to Set_Value or Reinitialize changes the value from the
+default to a non-default value (if the implementation chooses to
+optimize the default values in a way that eliminates the need for
+storage until a nondefault value is assigned).
+
+If you need to think in terms of scope, the scope of the
+task attributes is the same as that of the "task control block"
+object in the Ada runtime system.
+
+| > 2) You have no choice but to use another task in the case where the
+| > task was never activated.
+
+| And since no such task is available in general, it can only be done at the
+| appropriate point by launching an extra task to do it. (The task supervisor
+| itself can't call user code, as that might call back into the task
+| supervisor, which could deadlock or worse.)
+
+Well.... you have hit a tender spot.  (By the way, what exactly is
+the "task supervisor"?  We don't have one in GNARL.)  The notion
+of finalization is already inherently risky, given that it can
+take place after a task has been aborted, and during finalization
+abort is deferred.  This means that if a finalizer gets stuck in
+a loop or such, there is no way to kill the task.  This problem was
+known from the beginning, and it was accepted that finalizers are
+critical code, that must be very tightly verified and kept simple.
+Finalization of a task attribute may be a tiny bit riskier, if there
+is more than one task who can do it, since there must be some kind of
+lock that prevents concurrent finalizations of the same object, and
+that lock could cause a deadlock if the finalizer runs amok.
+Does this seem bad?  I don't see it as any worse than any other
+way a program can run amok, since all Ada tasks are in the same
+logical address space (due to stack and pointer sharing), and so
+may easily trash both each other's states and that of the Ada
+runtime system if they run badly amok.
+
+| You have convinced me that it is impossible to correctly implement these
+| things (at least in Janus/Ada). Or, at least that it is unbearably
+| expensive. And all for a feature of very little benefit (tasks don't
+| terminate very often in real Ada programs, as they usually are either
+| library level or declared by an access to task at the library level). (The
+| memory deallocation is not a problem, as it can occur along with
+| deallocation of other task structures).
+
+| The problem, of course, is the use of controlled types as task attributes.
+| The only solution I see is prohibiting them altogether. I doubt I could get
+| enough support for that in RM, but an implementation can do it with creative
+| use of C.7.2(18). I recommend that to all of the implementors.
+
+I do agree that allowing task attributes of controlled types turned
+out to be more costly and riskier than I had expected when it went into
+Ada 9X.  At this point I would not personally object to a langauge
+change that dropped this feature completely, but I expect there would
+be users who would object.  Therefore, I think the best solution is
+to leave it as is, and don't tighten the semantics or validation
+tests.  Any such tightening would just hurt implementors, and
+by extension users.
+
+| (For me personally, a better solution would be to burn all of my Ada books
+| and go bag groceries -- I'd make more money that way...)
+
+That is too painful.
+
+*************************************************************
+
+From: Ted Baker
+Sent: Friday, May 19, 2000 5:39 PM
+
+| Our task supervisor cannot call user code (it's not reentrant when a context
+| switch is required, as there is only a single save area); it has to use
+| another task to finalize things. And forcing a task to finalize something is
+| a one-way trip: it's not possible to return to what it was previously doing
+| (because the saved registers, etc, would be killed if it swapped out). So
+| the only way to handle unactivated tasks would be a spawn a task
+| specifically to call the finalize.
+
+In GNARL the whole runtime system is layered over a thread
+implementation, and so if there is anything like a "supervisor" it
+is in the thread layer.  The finalization of task attributes is
+done by the master of the task when it leaves the scope of the
+task or task access types declaration, or by the task that does an
+unchecked deallocation (if any) on the task object.
+
+I agree that this call-out to execute the finalizers makes me feel
+as if walking on very thin ice, since the call is made with the
+runtime system lock of the task held locked.  A bad finalizer
+could deadlock.
+
+| I find this whole thing quite dubious, because in practice, Ada tasks don't
+| terminate until the program does. The only time I've seen tasks terminate
+| before the end of the program is in validation tests and in a couple of test
+| programs I constructed to make sure that the resources are recovered at that
+| point. But end users tend to call and complain that the resources (mainly
+| memory) aren't recovered when the task is completed: which isn't possible in
+| Ada 95 because the task has to run to execute finalizations. They mistake
+| completion for termination. That distinction is confusing enough (and that
+| is why I object to any semantics that implies that terminated tasks can run,
+| even for a short period). Anyway, when these things are finalized is
+| unlikely to matter to most programs, simply because all of the tasks
+| terminate along with the application. Similarly storage leakage of
+| attributes is nearly irrelevant.
+
+| It is interesting to note that the only reason that this package even has
+| *anything* to do with the task supervisor is C.7.2(17). Otherwise, it is
+| simple stand-alone library package.
+
+Right.  The hook back into the tasking runtime system is very
+awkward.
+
+| Perhaps something on the line of Ted's idea is right: change C.7.2(17) into
+| an implementation permission. Then there would be no requirement to finalize
+| these things at an particular point, and the problems would go away -- they
+| could be finalized as late as the ending of the application. As it is, the
+| only viable alternative for Janus/Ada is to completely prohibit the use of
+| controlled types in Ada.Task_Attributes -- because the work involved in
+| getting this to work right far exceeds any possible benefit.
+
+I would not object to that resolution.
+
+*************************************************************
+
+From: Ted Baker
+Sent: Friday, May 19, 2000 5:49 PM
+
+| It is unfortunate that the RM doesn't talk explicitly about what
+| happens when an instantiation of Ada.Task_Attributes is
+| finalized.  Our implementation happens to follow the same
+| approach as Mike suggests, namely finalizing the attribute in
+| all tasks when the instantiation is finalized, but it is hard to
+| find a requirement for that in the RM (other than the usual
+| underlying reasonableness requirement that Robert Dewar mentions
+| now and then ;-).
+
+GNARL also finalizes all the instances of a given attribute when
+the scope of the package instance is left.  This is the only
+sensible thing to do.
+
+My own feeling at this point in the disucssion is that an
+implementation might do well to finagle an excuse to omit support
+for task attributes of a controlled type.  The only serious loss
+is the ability to stop storage leakage.  It would remove what may
+be a too-tempting "hook" for users to hang overly complex task
+finalization code, that could end up being very unreliable.
+
+*************************************************************
+
+From: Ted Baker
+Sent: Friday, May 19, 2000 6:07 PM
+
+| Well, I doubt that anyone would seriously argue that we don't want to
+| require finalization at this point. So, I think we need at add something
+| like
+|    "When the master of an instantiation of Ada.Task_Attributes is finalized,
+| the associated attribute for all tasks is finalized."
+| after C.7.2(13).
+
+| This has the advantage of making it clear what the master for task attribute
+| objects is, which makes the semantics much more deterministic. (The master
+| matters, of course, for types with controlled subcomponents).
+
+| I would argue that adding this rule makes C.7.2(17) unnecessary, so I would
+| suggest turning it into an implementation permission (so that existing
+| implementations would not have to change).
+|    "When a task terminates, an implementation may finalize all attributes of
+| the task, and reclaim any other storage associated with the attributes."
+
+| The second change would eliminate all of my objections/problems, and would
+| have very little effect on real programs (since tasks rarely terminate
+| before the entire program).
+
+| The need to spawn a task to finalize attributes when a task terminates is
+| far to heavyweight for a feature that will be rarely used (that is, the
+| combination of controlled task attributes and tasks that actually
+| terminate). I don't think that the expense to every tasking program (in
+| size, at least) and especially to every task that uses task attributes (even
+| of none of them are controlled) is justified.
+
+I would not object to this change, since it seems to be neutral or
+friendly to both vendors and users.
 
 *************************************************************
 

Questions? Ask the ACAA Technical Agent