CVS difference for ai05s/ai05-0111-3.txt

Differences between 1.11 and version 1.12
Log of other versions for file ai05s/ai05-0111-3.txt

--- ai05s/ai05-0111-3.txt	2011/04/26 07:20:19	1.11
+++ ai05s/ai05-0111-3.txt	2011/04/28 07:01:31	1.12
@@ -1,4 +1,4 @@
-!standard  4.8(2)                                   11-04-21    AI05-0111-3/09
+!standard  4.8(2)                                   11-04-28    AI05-0111-3/10
 !standard  4.8(3/2)
 !standard  4.8(10.3/2)
 !standard 13.11(16/3)
@@ -243,28 +243,6 @@
 an access type, the access type is called a *subpool access type*. A subpool
 access type shall be a pool-specific access type.
 
-A descendant of Root_Storage_Pool_with_Subpools shall not override Allocate.
-
-AARM Reason: This ensures that two implementation models are possible
-for an allocator with no subpool_specification. Note that the "supports
-subpools" property is not necessarily known at compile time, although it
-usually will be.
-
-    - The implementation can dispatch to Storage_Pools.Allocate. If the pool
-      supports subpools, this will call Allocate_From_Subpool with the default
-      subpool.
-
-    - The implementation can declare Allocate_From_Subpool as a primitive of
-      Root_Storage_Pool in the private part of Storage_Pools. This means that
-      the Allocate_From_Subpool for Root_Storage_Pool_with_Subpools overrides
-      that private one. The implementation can thus call the private one,
-      which will call Allocate for non-subpool-supporting pools.
-
-The two implementations suggested above have identical effect,
-because Allocate cannot be overridden for subpool-supporting pools.
-
-[end AARM Reason]
-
 The accessibility level of a subpool access type shall not be statically
 deeper than that of the storage pool object.
 
@@ -299,7 +277,31 @@
 gained. At this time, we are unable to come up with a set of rules for task
 termination that is both useful, and surely feasible to implement.
 
+Implementation Permissions
 
+When an allocator for a type whose storage pool is of type
+Root_Storage_Pool'Class is evaluated, but supports subpools, the
+implementation may call Allocate rather than Allocate_From_Subpool.
+Redundant[This will have the same effect, so long as Allocate has not been
+overridden.]
+
+AARM Reason: This ensures either of two implementation models are possible
+for an allocator with no subpool_specification. Note that the "supports
+subpools" property is not known at compile time for a pool of the class-wide type.
+
+    - The implementation can dispatch to Storage_Pools.Allocate. If the pool
+      supports subpools, this will call Allocate_From_Subpool with the default
+      subpool so long as Allocate has not been overridden.
+
+    - The implementation can declare Allocate_From_Subpool as a primitive of
+      Root_Storage_Pool in the private part of Storage_Pools. This means that
+      the Allocate_From_Subpool for Root_Storage_Pool_with_Subpools overrides
+      that private one. The implementation can thus call the private one,
+      which will call Allocate for non-subpool-supporting pools. The effect
+      of this implementation does not change if Allocate is overridden for
+      a pool that supports subpools.
+[end AARM Reason]
+
 13.11.5 Subpool Reclamation
 
 The following language-defined library procedure exists:
@@ -8676,5 +8678,391 @@
 some real-time systems, but also wouldn't make much sense with subpools)? This
 is the kind of data that we'll need (someday) to decide how tasks deallocated
 from a subpool ought to be handled.
+
+****************************************************************
+
+From: Jean-Pierre Rosen
+Sent: Tuesday, April 26, 2011  3:35 AM
+
+> Because terminate alternatives are primarily useful for library-level
+> tasks that live forever anyway; that it's, they're for shutting down
+> entire programs.
+
+I don't agree with that statement. I think few people use local tasks, but for
+those who do, terminate alternatives are the best way to terminate tasks,
+because it works if the master is completed due to unhandled exception, while
+shutdown entries need to be called from a catch-all exception handler that is
+easily forgotten.
+
+****************************************************************
+
+From: Robert Dewar
+Sent: Tuesday, April 26, 2011  4:41 AM
+
+I agree with JPR on this point
+
+****************************************************************
+
+From: Bob Duff
+Sent: Tuesday, April 26, 2011  9:20 AM
+
+> I agree in the sense that I don't put much stock in the percentage of use.
+> But it is interesting that I found 7 uses of terminate alternatives in
+> my small set of "real" programs while Bob only found 2 in your entire
+> test suite of 10 million lines.
+
+I think you're misunderstanding my experiment.
+I found a couple hundred terminate alternatives.
+Approx 1% of all tests had at least one.
+
+What I was interested in was how many of those are nested; that is, how many are
+being used to terminate just PART of a program, rather than the whole thing.
+There were 2 of those.
+
+You reported how many task types and terminate alts are in your code, but you
+didn't say which ones were nested inside procedures or other tasks.  If it's not
+too much trouble, I'd be curious.
+
+> As I noted before, I'd be interested in how all of the "real" tasks
+> terminate. In particular, are they using shutdown entries (which won't
+> work with subpools) or some other technique?
+
+I don't agree that shutdown entries can't work with subpools.
+To use shutdown entries on heap-allocated tasks, you have to keep track of all
+the tasks (keep a linked list of them, for ex). Subpools wouldn't change that
+(assuming subpools allow tasks at all).
+
+If you allocate a million objects in a subpool, you don't want to call
+"Shutdown" on all of them -- you want to call "Shutdown" on the 50 of those that
+are tasks.  And you probably don't do that by looping through all million
+objects, and checking which ones are tasks.  ;-)
+
+>... Or do they not terminate at all
+> (which makes sense in some real-time systems, but also wouldn't make
+>much  sense with subpools)?
+
+Right.
+
+>...This is the kind of data that we'll need (someday) to  decide how
+>tasks deallocated from a subpool ought to be handled.
+
+I'm not sure I have the energy to gather more data right now.
+
+****************************************************************
+
+From: Bob Duff
+Sent: Tuesday, April 26, 2011  10:47 AM
+
+> What I was interested in was how many of those are nested; that is,
+> how many are being used to terminate just PART of a program, rather
+> than the whole thing.
+> There were 2 of those.
+
+Actually, I just realized my experiment was wrong.
+I found 2 terminate alternatives in non-library-level task bodies, but you could
+have a library-level task type, and create a more-nested object of that type.
+
+So I might have missed some.  And it's too hard to do this experiment properly,
+so I give up.
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Tuesday, April 26, 2011  2:24 PM
+
+> Actually, I just realized my experiment was wrong.
+> I found 2 terminate alternatives in non-library-level task bodies, but
+> you could have a library-level task type, and create a more-nested
+> object of that type.
+
+No wonder I was confused. The location of the task type is irrelevant as to how
+it is used. It is most likely to be a library-level type, but it still might be
+allocated and deallocated dynamically (or using local variables).
+
+> So I might have missed some.  And it's too hard to do this experiment
+> properly, so I give up.
+
+I agree; I don't know of any easy way to figure out when task objects (as
+opposed to task types) are created and destroyed. Perhaps it would be possible
+to instrument a compiler to gather that information, but then cross-referencing
+it to the form of the task body is even harder (as they don't have to be in the
+same compilation unit).
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Tuesday, April 26, 2011  2:34 PM
+
+...
+> I think you're misunderstanding my experiment.
+> I found a couple hundred terminate alternatives.
+> Approx 1% of all tests had at least one.
+>
+> What I was interested in was how many of those are nested; that is,
+> how many are being used to terminate just PART of a program, rather
+> than the whole thing.
+> There were 2 of those.
+
+As you later noted, you can't tell this syntactically.
+
+> You reported how many task types and terminate alts are in your code,
+> but you didn't say which ones were nested inside procedures or other
+> tasks.  If it's not too much trouble, I'd be curious.
+
+None of the tasks I looked at are nested. That makes sense, given that I try to
+avoid nesting.
+
+I would expect that any task used with a subpool would also be at library-level,
+as it is highly likely that's where the access types would be. But it wouldn't
+necessarily mean that they wouldn't be destroyed early.
+
+> > As I noted before, I'd be interested in how all of the "real" tasks
+> > terminate. In particular, are they using shutdown entries (which
+> > won't work with subpools) or some other technique?
+>
+> I don't agree that shutdown entries can't work with subpools.
+> To use shutdown entries on heap-allocated tasks, you have to keep
+> track of all the tasks (keep a linked list of them, for ex).
+> Subpools wouldn't change that (assuming subpools allow tasks at all).
+
+Exactly, but that is precisely what subpools are intended to change (needing to
+keep a list of all of the items in order to free them individually).
+
+> If you allocate a million objects in a subpool, you don't want to call
+> "Shutdown" on all of them -- you want to call "Shutdown" on the 50 of
+> those that are tasks.  And you probably don't do that by looping
+> through all million objects, and checking which ones are tasks.  ;-)
+
+But if your program is well-structured, you don't necessarily know which ones
+contain tasks, as that is just an implementation detail. (Remember, I'm thinking
+about the future with the thousand core CPUs, in which there will be a task for
+pretty much anything that can be executed asynchonrously.)
+
+Calling any sort of shutdown routine does not make much sense with the use of
+subpools, because it requires some sort of enumeration of the contents of the
+subpool, which is precisely what subpools are trying to avoid. Also, as J-P
+noted, such a routine is much more error-prone than having it happen
+automatically, so it ought to be avoided when possible on that basis alone.
+
+****************************************************************
+
+From: Bob Duff
+Sent: Tuesday, April 26, 2011  3:04 PM
+
+In all this talk about terminate alternatives, don't forget that they don't work
+at all for protected records -- only for tasks that wait on their own entries
+via accept statements.
+
+...
+> > I don't agree with that statement. I think few people use local
+> > tasks,
+
+I decided to do another little experiment to test that hypothesis.
+Hopefully I did it right this time.
+
+I ran 12953 tests with restriction No_Task_Hierarchy forced on.
+But not in library subprograms (because those are typically artificial tests).
+
+27 tests failed.
+27 / 12953 = 0.0021 .
+
+47 violations in 27 tests.
+
+Some of those 27 are artificial tests, but I didn't count how many.
+
+> > but for those who do, terminate alternatives are the best way to
+> > terminate tasks, ...
+
+12 of the 27 tests contain terminate alts.
+There are 27 terminate alts in those 12 tests.
+
+>...because it works if the master is completed due to
+> > unhandled exception, while shutdown entries need to be called from a
+> > catch-all exception handler that is easily forgotten.
+>
+> I agree with JPR on this point
+
+Apparently approx 12 other programmers do, too.  ;-)
+
+Randy asked for the total number of tasks:
+
+761 tests out of 12953 contain at least one task body
+(1263 task bodies in all).
+761 / 12953 = 0.059 .
+
+If you don't count library procedures,
+299 tests out of 12953 contain at least one task body
+(509 task bodies in all).
+
+27 / 299 = 0.090
+
+****************************************************************
+
+From: Jean-Pierre Rosen
+Sent: Wednesday, April 27, 2011  12:19 AM
+
+> I agree; I don't know of any easy way to figure out when task objects
+> (as opposed to task types) are created and destroyed. Perhaps it would
+> be possible to instrument a compiler to gather that information, but
+> then cross-referencing it to the form of the task body is even harder
+> (as they don't have to be in the same compilation unit).
+
+No kidding! In AdaControl:
+check local declarations(Task);
+check allocators (task);
+
+TBH, the first one will find all non global task types and single task objects,
+but not declarations of a variable of a task type. Just an oversight, I can add
+the rule in minutes if you ask me.
+
+****************************************************************
+
+From: Jean-Pierre Rosen
+Sent: Wednesday, April 27, 2011  12:26 AM
+
+> In all this talk about terminate alternatives, don't forget that they
+> don't work at all for protected records -- only for tasks that wait on
+> their own entries via accept statements.
+
+True, but irrelevant. In any case, terminate alternatives are always on the
+server side. On the client (caller) side, there is never terminate alternatives.
+And there is no such thing as a server task with PO.
+
+****************************************************************
+
+From: Bob Duff
+Sent: Wednesday, April 27, 2011  6:48 AM
+
+> True, but irrelevant. In any case, terminate alternatives are always
+> on the server side. On the client (caller) side, there is never
+> terminate alternatives. And there is no such thing as a server task with PO.
+
+Lots of programs use PO's only, and no rendezvous.
+
+****************************************************************
+
+From: Bob Duff
+Sent: Tuesday, April 26, 2011  8:57 AM
+
+> I suppose you are right, although the only way I can think of to
+> implement this rule is to implement an aspect or pragma to set a
+> symboltable bit. So I'll end up with an implementation-defined aspect
+> instead of a language-defined one. It would be better if everyone came
+> up with the same aspect (rather the a half dozen similar ones); it
+> would be better to agree on such an aspect (perhaps informally) and have everybody implement that.
+
+Or drop that rule.  It's really not essential.  It would mean that anybody who
+overrides that thing gets impl-def semantics.  We could add a comment to that
+effect.
+
+I have no strong opinion on this.  I certainly agree that the rule as written is
+a kludge.
+
+****************************************************************
+
+From: Jean-Pierre Rosen
+Sent: Tuesday, April 26, 2011  10:05 AM
+
+> Or drop that rule.  It's really not essential.  It would mean that
+> anybody who overrides that thing gets impl-def semantics.  We could
+> add a comment to that effect.
+>
+
+I agree with Bob here. I really feel uncomfortable with a "final" method
+- in all Java examples I've seen, I could relate that to the absence of
+class-wide types (i.e. final classes are really used as class wide). Even more
+uncomfortable if there is some compiler magic that is not accessible to the
+casual user.
+
+And I don't view being final as an "aspect". Stretching a functionnality to
+being used in other than the reasonable, original intended usage is what created
+the pragma mess that we are now trying to fix...
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Tuesday, April 26, 2011  2:27 PM
+
+...
+> And I don't view being final as an "aspect". Stretching a
+> functionnality to being used in other than the reasonable, original
+> intended usage is what created the pragma mess that we are now trying
+> to fix...
+
+Well, it's hardly any different than the "Is_Synchronized" aspect (or whatever
+name it has today), which also affects legality rules. And an aspect is better
+than a pragma, as it doesn't get separated from the declaration. I'm not sure
+what else we could use; proper syntax is overkill for most of these things.
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Tuesday, April 26, 2011  2:42 PM
+
+> Or drop that rule.  It's really not essential.  It would mean that
+> anybody who overrides that thing gets impl-def semantics.  We could
+> add a comment to that effect.
+>
+> I have no strong opinion on this.  I certainly agree that the rule as
+> written is a kludge.
+
+Impl-def behavior is fine, but we need more than a "comment" about it.
+
+An alternative would be to declare it a bounded error (since there really are
+only two possible behaviors). That would look something like:
+
+Bounded Errors
+
+It is a bounded error to execute an allocator without an explicit subpool handle
+if the Allocate procedure of a pool with subpools is overridden. Program_Error
+is raised if the error is detected, otherwise the behavior is either as
+described for a pool with subpools, or as described for a storage pool that does
+not have subpools.
+
+AARM Note: That means that either Allocate_from_Subpool is called using the
+Default_Subpool_Handle, or the overridden Allocate procedure is called. The
+language does not specify which.
+
+This seems a bit better to me, as it suggests that you shouldn't write such an
+overriding, and it would let a tool like Ada Control check this and complain
+about the potential bounded error. And it prevents implementations from doing
+something else (which makes no sense at all).
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Wednesday, April 27, 2011  1:18 PM
+
+Could you decide what you want to do here? I'd like to know before I send this
+AI to a vote.
+
+If you'll tell me which option you want to follow, I can make the changes
+(they're pretty minor).
+
+Choices: (1) Keep the kludgy rule;
+         (2) Somehow say that the results are implementation-defined (you'll
+             have to word this);
+         (3) Make it a bounded error as I proposed previously;
+         (4) Something else??
+
+****************************************************************
+
+From: Bob Duff
+Sent: Wednesday, April 27, 2011  1:37 PM
+
+(5) I don't care.  ;-)
+
+I guess I prefer (1), second choice (2).
+Wording for (2) would be:
+
+                          Implementation Permissions
+
+  When an allocator for a type whose storage pool is of type
+  Root_Storage_Pool'Class is evaluated, but supports subpools, the
+  implementation may call Allocate rather than Allocate_From_Subpool.
+  Redundant[This will have the same effect, so long as Allocate has not been
+  overridden.]
+
+And delete the kludgy rule, as well as the AARM note explaining why it exists.
 
 ****************************************************************

Questions? Ask the ACAA Technical Agent