CVS difference for ais/ai-00162.txt

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

--- ais/ai-00162.txt	1998/10/03 04:28:53	1.2
+++ ais/ai-00162.txt	2003/11/27 02:01:11	1.3
@@ -515,3 +515,550 @@
 -Tuck
 
 ****************************************************************
+
+From: Stephen W. Baird
+Sent: Thursday, October 30, 2003  11:31 AM
+
+This is a preliminary discussion of AI-162, as per my homework
+assignment from the Sydney ARG meeting.
+
+--------------------------------
+
+Allocators of anonymous access types introduce a fairly large amount of
+complexity to the dynamic semantics of Ada.
+
+This complexity is in some sense proportional to the product of two sets:
+the set of contexts in which an anonymous access type may occur and a set
+of issues which must be resolved for each context.
+
+The set of contexts in which an anonymous access type may occur includes
+    - as a discriminant type of a "really limited" type
+    - as a formal parameter type
+    - as a "garden variety" component type (proposed in AI 230)
+    - as a function result type (proposed in AI 325)
+
+The set of issues includes
+    - determining the point of finalization for the allocated object
+    - determining the master of any task parts of the allocated object
+    - determining the storage_pool to be used by the allocator
+    - determining the point of reclamation for the allocated object's storage
+    - determining the accessibility level of the access value
+
+This leads to the question of how best to express the desired rules.
+
+One could distribute them throughout the manual, adding provisions for
+each of the listed contexts to (at least) 3.10.2, 7.6.1, 9.3, and 13.11.
+This would require lots of changes (each of several lines) with the
+resulting logic scattered nearly to the point of unreadability.
+
+One might try to leverage the work that has already been done for
+allocators of named access types by using equivalence rules.
+In addition to the general objection "Equivalence rules never work", this
+approach has a more specific flaw.
+It relies on the assumption that for each allocator of an anonymous access
+type, there exists a point where a named access type could have been
+declared and which would have resulted in the same program behavior if
+that named type had been used as the type of the allocator.
+In the case of a function result, this assumption does not hold.
+
+I think the best of the available alternatives would be to add an entirely
+new section to the manual, perhaps 4.8.1.
+The passages mentioned above (3.10.2, 7.6.1, 9.3, and 13.11) would each
+contain a one-line reference to the new section.
+This seems like overkill for dealing with what seems like an obscure
+corner case, but it is better than the alternatives.
+
+Before I go any further with this, I would like to get the opinion of the
+ARG as to whether I am on the right track.
+
+P.S.
+
+An_Only_Tangentially_Related_Rant:
+  begin
+
+    I believe the utility of anonymously-typed allocators does not justify
+their complexity, that allowing them  was a language design
+   mistake, and that AIs 230 and 325 (which, ignoring allocators, seem
+reasonable to me) increase the impact of this error.
+
+    I recognize, however, that my opinion on this subject is not widely
+shared and that an incompatible change in this area is not a realistic
+option.
+
+    I also concede that it would seem odd to continue to allow anonymously
+typed allocators in some contexts while disallowing them in
+    the new contexts proposed  in AIs 230 and 325.
+
+  end An_Only_Tangentially_Related_Rant;
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Thursday, October 30, 2003  12:00 PM
+
+...
+> This leads to the question of how best to express the desired rules.
+>
+> One could distribute them throughout the manual, adding provisions for
+> each of the listed contexts to (at least) 3.10.2, 7.6.1, 9.3, and 13.11.
+> This would require lots of changes (each of several lines) with the
+> resulting logic scattered nearly to the point of unreadability.
+
+So what else is new?  But seriously, we do this for essentially
+every construct.  I don't know why anonymous allocators need
+"special" treatment.  Programmers just want them to work.
+Implementors can deal with scattered definitions.
+
+> ...
+> I think the best of the available alternatives would be to add an entirely
+> new section to the manual, perhaps 4.8.1.
+> The passages mentioned above (3.10.2, 7.6.1, 9.3, and 13.11) would each
+> contain a one-line reference to the new section.
+> This seems like overkill for dealing with what seems like an obscure
+> corner case, but it is better than the alternatives.
+
+I don't agree.  I don't see sufficient benefit to justify
+creating a separate section.
+
+> Before I go any further with this, I would like to get the opinion of the
+> ARG as to whether I am on the right track.
+
+I would add/fix the wording in the relevant sections.
+
+With your proposal, you will have to add/change/remove some amount
+of wording in each of these sections to point to the new
+section, plus write the wording in the new section, in each
+case creating sufficient context to link the wording back to
+the place where it is relevant.
+
+Sounds like a loser to me.
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Thursday, October 30, 2003  12:03 PM
+
+Steve wrote:
+
+> An_Only_Tangentially_Related_Rant:
+>   begin
+>
+>     I believe the utility of anonymously-typed allocators does not justify
+> their complexity, that allowing them  was a language design
+>    mistake, and that AIs 230 and 325 (which, ignoring allocators, seem
+> reasonable to me) increase the impact of this error.
+>
+>     I recognize, however, that my opinion on this subject is not widely
+> shared and that an incompatible change in this area is not a realistic
+> option.
+
+I agree with you 100% here. I think there would be some value to finding out
+how often this 'feature' is used. (I've never used it personally.) So far as
+I am aware, the support for this feature primarily comes from one very
+influental ARG member. If there really was a lot of interest in this, I
+think we would have accepted (with modifications), not killed, Mike Kamrad's
+version of this AI. (It, after all, is what is needed to solve this problem.
+I very much doubt that there is a substantially simpler solution that solves
+the problems.)
+
+>     I also concede that it would seem odd to continue to allow anonymously
+>     typed allocators in some contexts while disallowing them in
+>     the new contexts proposed  in AIs 230 and 325.
+
+There is another possibility which is not context-dependent and helps quite
+a bit. That would be to prohibit anonymous allocators if the designated type
+"needs finalization". Since we never figured out what that means, I suspect
+that using such a thing would get you into trouble on many compilers.
+They'll do *something*, but exactly what isn't clear (and it may not be
+useful). I think Janus/Ada would generate an internal error because the
+finalization chain wouldn't have been set up (although I haven't tried it).
+
+That would limit the incompatibility, and completely eliminate the task
+master and finalization issues. Tucker's answer for the storage
+pool/reclamation problem seems OK (other than for AI-325, which I hope dies
+an early, well-deserved death).
+
+> I think the best of the available alternatives would be to add an entirely
+> new section to the manual, perhaps 4.8.1.
+> The passages mentioned above (3.10.2, 7.6.1, 9.3, and 13.11) would each
+> contain a one-line reference to the new section.
+> This seems like overkill for dealing with what seems like an obscure
+> corner case, but it is better than the alternatives.
+
+Without seeing wording, it's very hard to say for sure. But I don't really
+see the point; I doubt that you could share much between the rules to handle
+the various issues. (Especially if we have the guts to solve the messiest
+issues by banning them.)
+Without such sharing, there is little benefit to having the rules in the
+same place. And I don't think that there is much in common between a "task
+master" rule and a "storage pool" rule, for example.
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Thursday, October 30, 2003  12:20 PM
+
+I agree that they might have been a mistake, but they
+are definitely used now, and the new Ada 2005 uses are the *simpler*
+ones, since they are the cases that *do* correspond to
+named access types.  The tough ones are the old cases,
+in particular access discriminants of limited types.
+Of course, those are exactly the cases where they are
+most useful, where you couldn't easily write an equivalent
+"normal" allocator.
+
+If you use access discriminants, it is not particularly weird
+to want to initialize the access discriminant with an allocator.
+They allow you to overcome the limitation that you can't have discriminants
+of a record or floating point type.
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Thursday, October 30, 2003  12:30 PM
+
+One other point:
+
+> ... If there really was a lot of interest in this, I
+> think we would have accepted (with modifications), not killed, Mike Kamrad's
+> version of this AI. (It, after all, is what is needed to solve this problem.
+> I very much doubt that there is a substantially simpler solution that solves
+> the problems.)
+
+The problem is more one of description, since we don't currently
+have individual statements as masters.
+
+Implementors already know how to deal with aggregates and function calls
+that require finalization, so fitting task waiting into that
+can be relatively straightforward.  Chances are implementors who
+handle finalization right also do something reasonable with tasks.
+
+One possibility is to continue to ignore the task-waiting
+problem in the RM, and put in some kind of "to be honest".
+Or write something simple for the semantics, and allow
+more options via an implementation permission.
+
+(Without contract model problems, I don't see how to disallow
+creating tasks or controlled objects in anonymous allocators.)
+
+****************************************************************
+
+From: Stephen W. Baird
+Sent: Thursday, October 30, 2003  1:45 PM
+
+Tuck wrote:
+> I agree that they might have been a mistake, but they
+> are definitely used now, and the new Ada 2005 uses are the *simpler*
+> ones, since they are the cases that *do* correspond to
+> named access types.  The tough ones are the old cases,
+> in particular access discriminants of limited types.
+> Of course, those are exactly the cases where they are
+> most useful, where you couldn't easily write an equivalent
+> "normal" allocator.
+
+I disagree. If an allocator of an anonymous type is used as a
+discriminant of an limited type, then that is equivalent to declaring
+a named access type at the point of the constraint (not at the
+point of the limited type declaration) and using that for the type
+of the allocator. The exception to this is if the allocator is
+being used as a discriminant value to constrain another allocator,
+in which case the named access type would have to be declared at the
+point of the type of the second allocator (or, if the type of the second
+allocator is also anonymous, at the point where its equivalent named
+access type might have been declared - we assume inductively that such
+a point exists).
+
+The case where you can't write an equivalent normal allocator is
+the anonymous function result type case (AI-325). Here, for the first time
+(ignoring shared code generics; I haven't thought about them)
+we have an allocator whose accessibility level is not known statically.
+
+In particular, if the caller is more nested than the callee, then it
+would be very difficult to use a named access type for the type of
+the returned allocator.
+
+If it wasn't for this case, one could use equivalence rules in the RM
+and I would at least consider doing so.
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Thursday, October 30, 2003  3:29 PM
+
+I would recommend you not worry about AI-325 when working on AI-162.
+AI-325 may sink under its own weight anyway, and the worry about
+anonymous allocators in return statements is part of its weight,
+not AI-162's, at this point.  No need for you to unburden it.
+
+One other point I might mention.  There seems to be a fair
+amount of support for AI-287, "Limited Aggregates Allowed."
+If we presume that will happen, then we need to deal with
+tasks created by aggregates.  This seems very nearly identical
+to the problem associated with tasks created by anonymous
+allocators passed as a parameter.
+
+It would seem that 7.6.1(13) could be incorporated into the
+definition of master in 7.6.1(3), and then finalization and
+task waiting would be handled uniformly for statements or
+declarations containing such aggregates or anonymous allocators.
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Thursday, October 30, 2003  7:00 PM
+
+Tucker said:
+
+> I would recommend you not worry about AI-325 when working on AI-162.
+> AI-325 may sink under its own weight anyway, and the worry about
+> anonymous allocators in return statements is part of its weight,
+> not AI-162's, at this point.  No need for you to unburden it.
+
+Right. And technically, since AI-162 is not an amendment AI, it shouldn't
+consider AI-230 or any other amendment either.
+
+> One other point I might mention.  There seems to be a fair
+> amount of support for AI-287, "Limited Aggregates Allowed."
+> If we presume that will happen, then we need to deal with
+> tasks created by aggregates.  This seems very nearly identical
+> to the problem associated with tasks created by anonymous
+> allocators passed as a parameter.
+
+My initial reaction was no, they're only allowed in contexts where they are
+directly initializing an object. But that's not what the AI says. And,
+worse, there doesn't seem to be any semantics for passing an aggregate to a
+parameter of a by-reference type. So I have no idea what is supposed to
+happen here. (This would seem to be the case for Ada 95 as well, for tagged
+type aggregates.) The problem is that 6.4.1(10) talks about passing a "view
+conversion of the actual parameter". But view conversions are only defined
+for "the name of an object" 4.6(5/1). There is no object, only a value, for
+an aggregate. So what is going on?
+
+In any case, presuming you are right, any such wording belongs to AI-287 (it
+would be unfair to stuff it into some other AI with the claim that we have
+to do it anyway, because we clearly don't). Which, unfortunately, means
+reopening that AI.
+
+Earlier, Tucker said:
+
+>(Without contract model problems, I don't see how to disallow
+>creating tasks or controlled objects in anonymous allocators.)
+
+Well, Janus/Ada currently uses an assume-the-worst model: any program with
+such an allocator GP faults (which is certainly the worst that could happen
+;-). It clearly would be better to reject any such programs.
+
+Seriously, the language could use an assume-the-worst model, but that seems
+a bit strong. (Unless you want to ban such allocators altogether.) It also
+clearly could be a mixed legality/runtime check like accessibility. But I
+realize that's not particularly "clean".
+
+>The problem is more one of description, since we don't currently
+>have individual statements as masters.
+
+Right, but we have to have that (in some form) in order to deal with this
+problem.
+
+>Implementors already know how to deal with aggregates and function calls
+>that require finalization, so fitting task waiting into that
+>can be relatively straightforward.  Chances are implementors who
+>handle finalization right also do something reasonable with tasks.
+
+I don't think they are the same problem. Certainly some guy named Tucker
+thought that they were separate when it came up discussing AI-280: "Hence, I
+think this implies that if you have per-object work to do storage
+reclamation, finalizing a master requires three separate sequences:
+        1) wait for all subtasks
+        2) finalize all controlled/protected objects
+        3) reclaim all storage
+Trying to intermingle any of these three will violate the RM in my view."
+(message of Dec. 11, 2001) I don't see a practical RM wording that doesn't
+intermingle them.
+
+Similarly, finalization of anonymous access allocators is a completely
+separate problem from finalization of aggregates. The issue is that access
+types have their own, separate finalization list [as an access type is a
+master]. That list has to be initialized somewhere, and that requires
+special processing. Similarly for access type task masters. You'd have to do
+an extra scan of every statement's expression tree to see if any
+finalization chains or masters were needed.
+
+But I think you would prefer that this access "type" does not have the
+semantics of an access type at all. (That is, there is no separate
+finalization list, pool, and task master). That seems like a disaster; we'd
+have to look at every rule that involves tasks or finalization or pools and
+insure that they have the right wording to support such a "split".
+
+Implementation-wise, it would be worse: such an item would have to be
+represented differently than an access type in the compiler, and we'd have
+to check and in many cases do something different everywhere that an access
+type is used. A quick check of Janus/Ada's source shows 69 uses of "Is_Ptr",
+but the middle pass doesn't even use a special function: it assumes that all
+Ptr_Class types (that's a representation) are implemented the same way. I
+found over 550 uses of "Ptr_Class". (These counts probably are high, because
+of hits of entities that contain those phrases.) To find and change all of
+the placed needed to separately support such allocators would be daunting.
+
+In any event, such a model wouldn't completely work for Janus/Ada. For
+historical reasons, task masters are separate objects from the finalization
+chain (which implements masters in the language sense); they're linked onto
+the list at an appropriate place. So, while we might be able to get rid of
+the finalization chain for anonymous access types (although that seems
+sensible only for anonymous access used as a parameter), getting rid of the
+master isn't possible. We'd have to generate a statement level master for
+the access type, and that would be a new (and potentially expensive)
+construct.
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Thursday, October 30, 2003  8:26 PM
+
+> ...
+> > One other point I might mention.  There seems to be a fair
+> > amount of support for AI-287, "Limited Aggregates Allowed."
+> > If we presume that will happen, then we need to deal with
+> > tasks created by aggregates.  This seems very nearly identical
+> > to the problem associated with tasks created by anonymous
+> > allocators passed as a parameter.
+>
+> My initial reaction was no, they're only allowed in contexts where they are
+> directly initializing an object. But that's not what the AI says. And,
+> worse, there doesn't seem to be any semantics for passing an aggregate to a
+> parameter of a by-reference type.
+
+What is the confusion here?  An aggregate is a constant object (3.3(21)).
+It seems clear what it means to pass it by reference.
+
+> ... So I have no idea what is supposed to
+> happen here. (This would seem to be the case for Ada 95 as well, for tagged
+> type aggregates.) The problem is that 6.4.1(10) talks about passing a "view
+> conversion of the actual parameter". But view conversions are only defined
+> for "the name of an object" 4.6(5/1). There is no object, only a value, for
+> an aggregate. So what is going on?
+
+Aggregates are objects.  Also, values of a by-reference type have
+associated objects (see 6.2(10)).
+
+> In any case, presuming you are right, any such wording belongs to AI-287 (it
+> would be unfair to stuff it into some other AI with the claim that we have
+> to do it anyway, because we clearly don't). Which, unfortunately, means
+> reopening that AI.
+
+I'm not sure we need to do that.  I am suggesting that via AI-162 we
+create a general solution, not one tailored to anonymous allocators.
+Once we establish a master around a statement or declaration that
+can handle temporary tasks, finalizable objects, or short-lived
+anonymous access types, it should be relatively easy to deal
+with aggregates and anonymous allocators.
+
+> >The problem is more one of description, since we don't currently
+> >have individual statements as masters.
+>
+> Right, but we have to have that (in some form) in order to deal with this
+> problem.
+
+And aggregates containing tasks.
+
+> >Implementors already know how to deal with aggregates and function calls
+> >that require finalization, so fitting task waiting into that
+> >can be relatively straightforward.  Chances are implementors who
+> >handle finalization right also do something reasonable with tasks.
+>
+> I don't think they are the same problem. Certainly some guy named Tucker
+> thought that they were separate when it came up discussing AI-280: "Hence, I
+> think this implies that if you have per-object work to do storage
+> reclamation, finalizing a master requires three separate sequences:
+>         1) wait for all subtasks
+>         2) finalize all controlled/protected objects
+>         3) reclaim all storage
+> Trying to intermingle any of these three will violate the RM in my view."
+> (message of Dec. 11, 2001) I don't see a practical RM wording that doesn't
+> intermingle them.
+
+All very true, but they tend to happen at the same point.
+For example, in our compiler, we have a single "master" record
+which can have a list of tasks, and a list of cleanup actions.
+We first do all the finalization actions, and then we wait for
+all the tasks.  If we are also going to reclaim storage at this
+point, we do that after the finalization and task waiting.
+
+> Similarly, finalization of anonymous access allocators is a completely
+> separate problem from finalization of aggregates. The issue is that access
+> types have their own, separate finalization list [as an access type is a
+> master].
+
+An access type is not itself a master.  An access type is elaborated
+by some master, and that determines the master of the tasks
+created by allocators for the access type (9.3(2)).
+
+> ... That list has to be initialized somewhere, and that requires
+> special processing. Similarly for access type task masters. You'd have to do
+> an extra scan of every statement's expression tree to see if any
+> finalization chains or masters were needed.
+>
+> But I think you would prefer that this access "type" does not have the
+> semantics of an access type at all. (That is, there is no separate
+> finalization list, pool, and task master). ...
+
+No, I am not saying that.  All I am recommending is that they
+all share a single master from a languge description point of view,
+which seems appropriate, given the fact that an access type is
+not itself a master.  I don't want to get into the business of
+telling you how to implement this at a detailed level.
+
+I am simply arguing that many implementors (not all) use
+much of the same mechanism for finalization and task waiting,
+and we should take advantage of that by having aggregates
+and these kinds of short-lived anonymous access types share
+the same master.  Obviously you don't have to take advantage
+of that.  But we certainly shouldn't require that the finalization
+and the task waiting happen at different points.
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Thursday, October 30, 2003  9:00 PM
+
+Tucker replied to me:
+
+> > But I think you would prefer that this access "type" does not have the
+> > semantics of an access type at all. (That is, there is no separate
+> > finalization list, pool, and task master). ...
+>
+> No, I am not saying that.  All I am recommending is that they
+> all share a single master from a languge description point of view,
+> which seems appropriate, given the fact that an access type is
+> not itself a master.  I don't want to get into the business of
+> telling you how to implement this at a detailed level.
+
+Feel free. Your model may make more sense. :-)
+
+> I am simply arguing that many implementors (not all) use
+> much of the same mechanism for finalization and task waiting,
+> and we should take advantage of that by having aggregates
+> and these kinds of short-lived anonymous access types share
+> the same master.  Obviously you don't have to take advantage
+> of that.  But we certainly shouldn't require that the finalization
+> and the task waiting happen at different points.
+
+That I certainly can agree with. It would be harder still if the task master
+(for waiting) was inconsistently positioned. (We do use the finalization
+mechanism for determining the actual point of triggering of waiting, because
+that automatically handles exceptions and aborts. But it is a separate
+object placed on the finalization chain at the right point. Storage
+management for user-accessible objects (not temporaries) will be done the
+same way when I get around to changing it.)
+
+My problem is figuring out how to declare a temporary task master object
+(which contains the waiting links) at some point where such things are not
+expected. Declaring task masters is messy, because we don't want to generate
+one unless we're sure we need it (if one is generated, the tasking runtime
+is required in the program, which is not true otherwise. And they're
+relatively expensive to initialize, as doing so requires a task supervisor
+call). Indeed, this is one of the very few places where we diverge from a
+pure-one-pass design, and it's because we do that that it becomes messy. But
+this is probably not a language issue.
+
+****************************************************************
+

Questions? Ask the ACAA Technical Agent