CVS difference for ai05s/ai05-0111-3.txt
--- ai05s/ai05-0111-3.txt 2011/04/12 07:01:25 1.10
+++ ai05s/ai05-0111-3.txt 2011/04/26 07:20:19 1.11
@@ -1,4 +1,4 @@
-!standard 4.8(2) 11-04-11 AI05-0111-3/08
+!standard 4.8(2) 11-04-21 AI05-0111-3/09
!standard 4.8(3/2)
!standard 4.8(10.3/2)
!standard 13.11(16/3)
@@ -38,11 +38,10 @@
at the point of the allocator. The subset can then be reclaimed at one
time with a single deallocation call.
-This is exactly as safe as reclaiming the objects one at a time with
-Unchecked_Deallocation (in that dangling pointers can be created). However,
-this approach adds flexiblity in storage management (as the memory can be
-reclaimed with a single operation), and can be used as a building block
-for safer allocations.
+This can create dangling pointers, as can Unchecked_Deallocation. However,
+managing entire groups of objects at once is much less error prone. It is also
+likely to be much more efficient. Subpools can also be used as a building
+block for safer allocation strategies.
!proposal
@@ -71,9 +70,9 @@
Add at the end of 4.8(3/1):
- The expected type for a *subpool_handle*_name is Subpool_Handle, the type
- used to identify a subpool, declared package System.Storage_Pools.Subpools
- (see 13.11.4).
+ A *subpool_handle*_name is expected to be of any type descended from
+ Subpool_Handle, the type used to identify a subpool, declared in package
+ System.Storage_Pools.Subpools (see 13.11.4).
Add after 4.8(5/2):
@@ -159,20 +158,21 @@
-- Create subpool within given storage pool.
-- NOTE: Additional functions that create subpools may be
-- defined for a given storage pool that supports subpools.
- -- [Editor's Note: This uses AI05-0143-1 to allow an in out parameter;
- -- "access" could be used instead but would be less convenient.]
+ -- [Editor's Note: This uses AI05-0143-1 to allow an in out parameter; "access"
+ -- could be used instead but would be less convenient.]
+ -- Will typically call Set_Pool_of_Subpool, so the newly created
+ -- subpool belongs to Pool.
function Pool_of_Subpool(Subpool : not null Subpool_Handle)
return access Root_Storage_Pool_with_Subpools'Class;
- -- Return access to underlying storage pool of given handle.
+ -- Return access to the storage pool the Subpool belongs to.
procedure Set_Pool_of_Subpool(Subpool : not null Subpool_Handle;
To : in out Root_Storage_Pool_with_Subpools'Class);
- -- Set the Pool for a newly created subpool or a subpool that
- -- is being reused after a call to Unchecked_Deallocate_Subpool.
+ -- Causes the Subpool to belong to the given pool.
-- This is intended to be called from Create_Subpool or similar
-- subpool constructors.
- -- Raises Program_Error if the Pool already belongs to a pool.
+ -- Raises Program_Error if the Subpool already belongs to a pool.
procedure Allocate_From_Subpool(
Pool : in out Root_Storage_Pool_with_Subpools;
@@ -226,83 +226,6 @@
end System.Storage_Pools.Subpools;
-AARM Discussion:
-
-Keep in mind three responsibilities regarding subpools:
-
-Ada implementation. The Ada implementer is responsible for the following:
-
- - Implemention of the concrete operations: primarily Pool_of_Subpool and
- Set_Pool_of_Subpool. The full type of Root_Subpool can contain a pointer
- to the pool. Also Allocate and Deallocate, although these are not
- normally used.
-
- - The full type of Root_Subpool can contain a doubly-linked list of
- objects that need finalization. "new" adds objects to the
- list. Unchecked_Deallocation finalizes the object, removes it from
- the list, and calls Deallocate. By default, Deallocate does
- nothing; memory is normally reclaimed later, by
- Unchecked_Deallocate_Subpool, or by finalization of the subpool.
-
- - Finalization of a Root_Storage_Pool_with_Subpools must finalize
- all remaining subpools.
-
-Memory Management. An Ada programmer who wishes to implement memory management
-is responsible for the following:
-
- - Declare concrete types derived from Root_Storage_Pool_with_Subpools and
- Root_Subpool.
-
- - Implement the abstraction operations: Create_Subpool,
- Allocate_From_Subpool, and Deallocate_Subpool.
-
- - Possibly implement additional subpool-creation functions, for example a
- Create_Subpool that takes a Storage_Size parameter to limit on the amount
- of storage for the subpool.
-
- - If a default subpool is desired, override Default_Subpool_for_Pool.
- Possibly provide a Set_Default_Subpool_for_Pool operation.
-
- - Deallocate may be overridden, if desired. If so, it will normally need a
- way to find the subpool from the address of the object. If not, the
- default "null" version will be used, and memory will be reclaimed for the
- entire subpool at once. Note that there is no Deallocate_From_Subpool;
- Unchecked_Deallocation calls Deallocate, as for a pool that does not
- support subpools.
-
- Note that Allocate and Deallocate for Root_Storage_Pool are abstract. It
- is important that we provide concrete overridings for
- Root_Storage_Pool_with_Subpools, because these operations are not very
- useful, and otherwise, memory management programmers would be forced to
- override them.
-
-Application. An application programmer who wishes to use subpools is
-responsible for the following:
-
- - Use the "for Access_Type use ..." syntax to attach a subpool-supporting
- pool to each access type. Typically, many access types can share the same
- pool.
-
- - Create subpool objects by calling Create_Subpool. Alternatively, declare
- subpool objects and attach them to the pool with Set_Pool_of_Subpool.
-
- - Use the "new (Some_Subpool) T ..." syntax to allocate objects in
- particular subpools. Typically, many objects with similar lifetimes will
- be allocated in a particular subpool.
-
- - Use the "new T ..." syntax to allocate objects in the default subpool.
- Possibly call Set_Default_Subpool_for_Pool, if it exists.
-
- - Perform finalization and memory reclamation by calling
- Unchecked_Deallocate_Subpool. Alternatively, simply let a declared
- subpool go out of scope.
-
- - Perform finalization on a particular object by calling
- Unchecked_Deallocation. However, this will not reclaim memory, unless the
- subpool overrides Deallocate to do so.
-
-[end AARM Discussion]
-
A *subpool* is a separately reclaimable portion of a storage pool, identified by
an object of type Subpool_Handle (a *subpool handle*). A subpool handle also
identifies the enclosing storage pool, a *storage pool that supports subpools*,
@@ -352,11 +275,12 @@
the storage pool object. Program_Error is raised if this check fails.
AARM Reason:
- This check (and its static counterpart) ensures that the type of the allocated
- objects exist at least as long as the storage pool object, so that the subpools
- are finalized (which finalizes any remaining allocated objects) before the type
- of the objects ceases to exist. The access type itself will cease to exist before
- the storage pool.
+ This check (and its static counterpart) ensures that the type of the
+ allocated objects exist at least as long as the storage pool object, so that
+ the subpools are finalized (which finalizes any remaining allocated objects)
+ before the type of the objects ceases to exist. The access type itself (and
+ the associated collection) will cease to exist before the storage pool ceases
+ to exist.
A call to Subpools.Allocate(P, Addr, Size, Align) does the following:
@@ -366,6 +290,16 @@
Subpool => Default_Subpool_for_Pool
(Root_Storage_Pool_with_Subpools'Class(P)));
+
+An allocator that allocates in a subpool raises Program_Error if the allocated
+object has task parts.
+
+AARM Reason: This is to ease implementation. We envision relaxing this
+restriction in a future version of Ada, once implementation experience has been
+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.
+
+
13.11.5 Subpool Reclamation
The following language-defined library procedure exists:
@@ -376,13 +310,12 @@
A subpool may be explicitly deallocated using Unchecked_Deallocate_Subpool.
If Subpool is null, a call on Unchecked_Deallocate_Subpool has no
-effect. Otherwise, the subpool is finalized, and it no longer belongs to any
-pool. Finally, Subpool is set to null.
+effect. Otherwise, the subpool is finalized, and Subpool is set to null.
-Unchecked_Deallocate_Subpool is a potentially blocking operation (see 9.5.1).
-
Finalization of a subpool has the following effects:
+* The subpool no longer belongs to any pool.
+
* Any of the objects allocated from the subpool that still exist
are finalized in an arbitrary order;
@@ -414,24 +347,8 @@
[end AARM Discussion]
- Bounded Errors
-
-It is a bounded error to allocate an object that has task subcomponents in a
-subpool.
-AARM Reason: This is to ease implementation. We envision relaxing this
-restriction in a future version of Ada, once implementation experience has been
-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.
-
-The possible effects are:
-
-* Program_Error is raised by the allocator.
-
-* The allocator proceeds as usual. In this case, the semantics for
- termination of such tasks are implementation defined.
-
13.11.6 Storage Subpool Example
The following example is a simple but complete implementation of the classic
@@ -619,8 +536,8 @@
Root_Storage_Pool_with_Subpools).
Meanwhile, the "root part" of the subpool object type will be used by
-the Ada implementation to implement and finalization for the subpools,
-as well as managing the connection between subpools and their parent
+the Ada implementation to implement finalization for the subpools,
+and to manage the connection between subpools and their parent
pool. (The Ada implementation may also use the "root part" of the
storage pool for this purpose.)
@@ -741,7 +658,11 @@
aspect, as the required access discriminant would prevent useful assignments.
But a helper function and object could do the job safely.
----
+!example
+
+See the example given in the !wording.
+
+----
Another way that subpools can be used is to partition data. Imagine a
long-running web server for a retail establishment, which builds up
@@ -762,31 +683,6 @@
separately reclaimable item, namely one for each customer historical record,
one for each product description, and one for each shopping cart.
-!example
-
-See the example given in the !wording.
-
----
-
-Another way that subpools can be used is to partition data. Imagine a
-long-running web server for a retail establishment, which builds up in-memory
-representations of
-historical customer information, current product information, and each
-active customer's current shopping cart. There is a desire to be able to
-reclaim this in-memory information when it has not been recently
-referenced. However, the various representations are interlinked, such
-that a shopping cart refers to the in-memory representation for the
-products it contains, and the historical customer information and the
-current shopping cart might refer to each other.
-
-Although these representations might be made up of multiple heap objects,
-linked into hash tables, sets, lists, trees, etc., reclamation generally
-happens at the unit of an entire customer history, shopping cart, or
-product description, so there is a desire to avoid individual object-by-object
-deallocation. Hence, we would establish a separate subpool for each
-separately reclaimable item, namely one for each customer historical record,
-one for each product description, and one for each shopping cart.
-
!ACATS test
Create ACATS C-Tests to test this facility.
@@ -6893,3 +6789,1892 @@
****************************************************************
+From: Robert Dewar
+Sent: Tuesday, April 12, 2011 2:34 AM
+
+> You removed "with System.Storage_Elements;" from the subpool package.
+>
+> My personal style is to always include withs of packages that are
+> actually referenced in a child package on that package, whether or not
+> they are withed on the parent package. That is clearer to readers, and
+> allows maintenance on the parents without worrying about the children.
+>
+> I don't think the Standard has a style for this particular case, so I
+> would prefer to have this with on the package.
+
+To me, this extra with seems odd ...
+
+I definitely would prefer not to do this in the standard, since it creates
+confusion, given that the standard quite clearly says that it is not necessary.
+
+I understand that you prefer this style, but if the standard preferred this
+style, it would have made it mandatory.
+
+****************************************************************
+
+From: Bob Duff
+Sent: Tuesday, April 12, 2011 8:27 AM
+
+> Some reasonably minor comments on your redraft (note: I didn't make
+> any fixes at all other than to remove extra spaces after periods):
+
+Thanks for reviewing it. I'll produce a new version with minor changes.
+Anybody else want to weigh in first?
+
+And I guess I need a few answers from you, Randy (see below) before producing
+the new one.
+
+> You changed the wording of 4.8(3/1) from:
+>
+> A *subpool_handle*_name is expected to be of any descendant of
+> System.Storage_Pools.Subpools.Subpool_Handle, the type used to identify a sub
+> defined in the language-defined package System.Storage_Pools.Subpools (see 13.11.4).
+>
+> to
+>
+> The expected type for a *subpool_handle*_name is Subpool_Handle, the type
+> used to identify a subpool, declared package System.Storage_Pools.Subpools
+> (see 13.11.4).
+>
+> This eliminates the possibility to derive a type from Subpool_Handle
+> in the package for some user-written pool type. We previously decided
+> that this makes using a subpool-supporting pool much easier, and thus
+> we reworded this rule to allow derived types. (As we all know, a
+> subtype is not equivalent to a derived type, as no operators come
+> along.) Note that we did this in the example (haven't seen if you changed that or not).
+>
+> Did you do this intentionally (and if so, why - you didn't mention it
+> anywhere)?? Or were you just trying to reword this and lost an
+> intended capability?
+
+Yes, I did it intentionally. I thought it made sense for a client subpool to
+derive from Root_Subpool; deriving from Subpool_Handle seemed weird to me.
+
+The example uses a "renaming" subtype, and I didn't change that.
+
+I'm happy to put it back the way it was. No harm in allowing derived _Handle
+types.
+
+> ===================
+>
+> You removed "with System.Storage_Elements;" from the subpool package.
+>
+> My personal style is to always include withs of packages that are
+> actually referenced in a child package on that package, whether or not
+> they are withed on the parent package. That is clearer to readers, and
+> allows maintenance on the parents without worrying about the children.
+>
+> I don't think the Standard has a style for this particular case, so I
+> would prefer to have this with on the package.
+
+My personal style is to avoid optional with clauses.
+I suspect that's the RM style, too, given that I wrote large parts of it. On
+the other hand (sorry, John), maybe it never came up in the RM before.
+
+I have no strong feeling either way. It doesn't change the semantics, so lets
+hear from others, and take the majority opinion. So far: Robert and I like it
+without the "with", Randy wants to put the "with" back in.
+
+Does anybody else care?
+
+> ===================
+>
+> You changed the exception description for Set_Pool_of_Subpool from:
+> -- Raises Program_Error if the Pool has already been set for Subpool
+> -- since the last explicit finalization (if any) of the subpool.
+> to:
+> -- Raises Program_Error if the Pool already belongs to a pool.
+
+I changed this because there's no definition of what "explicit finalization"
+means. A call to Finalize(My_Subpool)?
+
+I added text to Unchecked_Deallocate_Subpool: "and it no longer belongs to any
+pool", which I think is what is intended. I can add text to Create_Subpool and
+Set_Pool_of_Subpool to further clarify (they say the right thing, except they
+don't use the word "belong").
+
+> Three problems with this: first, I can't find any definition of when a
+> subpool "belongs" to a pool; the only use of the term in normative
+> wording is in the allocator check, which hardly could be a normative
+> definition.
+
+OK, I'll try to complete that definition as above.
+
+> Second, there is nothing named Pool here; perhaps you meant Subpool??.
+
+Yes.
+
+> Third, there is no other text which says that this "belongs" state is
+> reset when the subpool is finalized -- that surely needs to be said
+> normatively.
+
+I added that under Unchecked_Deallocate_Subpool.
+
+> Similarly, a lot of the normative wording for Deallocate_Subpool has
+> disappeared (why?). Specifically: "..., and destroy the subpool.
+
+I didn't know what "destroy the subpool" means. I don't think it really means
+anything -- you can reuse the pool via Set_Pool_of_Subpool. So I didn't think
+this added any particular semantics, so I deleted it. (The interesting
+semantics here has to do with "belong" -- at any given time, a subpool either
+belongs to some pool, or not, and we need to clarify which operations change
+that state).
+
+>... The subpool
+> handle is set to null after this call." Where did this go?? You added
+>"Unchecked_Deallocate_Subpool calls this", but surely it can be called
+>directly, too, and if it is the subpool still has to be set to null (at
+>the very least, the option has to exist should the subpool object be
+>allocated from the heap). My preference is for this to be a
+>requirement on the Deallocate_Subpool implementation (that's what I
+>had here), as the checking for allocators depends on this, and it is
+>best to treat anything that violates this as erroneous.
+
+Unchecked_Deallocate_Subpool sets it to null (already true in the previous
+version of the AI). Unchecked_Deallocation of a subpool sets it to null (that's
+Ada 83 semantics!).
+
+So I didn't see any need for Deallocate_Subpool to set also it to null.
+Deallocate_Subpool would not normally be called directly.
+
+To me, it really seems weird to trust the programmer of Deallocate_Subpool to
+set it to null. And even wierder to do it twice. I think the language rules
+already make it clear that dereferencing dangling Subpool_Handles is erroneous,
+and that's true whether or not any of these operations null-out things.
+
+> ===================
+>
+> Your lengthy discussion note after the subpool package seems like too
+> much to put in the AARM. It looks like something that belongs in the
+> Rationale or an Ada textbook. It also seems to encourage dangerous usage of
+> subpools.
+
+OK, since you have substantial disagreements with this text, let's just delete
+it.
+
+...
+> ======================
+>
+> The Bounded Error
+>
+> I'm a bit worried about this error. You talked about relaxing the
+> "restriction" in the future, but I don't see how that will work. If an
+> implementation has just raised Program_Error for any contained tasks,
+> there is no future problem.
+>
+> But if the implementation allows the allocator, the termination
+> semantics are then implementation-defined. Since the same semantics as
+> U_D are easy, I suspect many implementations will do that. But then if
+> we want to apply "better" (different) semantics in the future, that
+> would break any code that depends on the implementation-defined semantics.
+>
+> Thus, we'll never be able to change this Bounded Error in the future
+> (unless no one supports tasks here, which I doubt will happen,
+> especially if my predictions about multicore come true).
+
+My intention is that GNAT will initially raise Program_Error.
+Later, when we get a chance to study the runtimes in more depth we might do
+something else, under an option. I'm not yet sure what "something else" is, and
+I'd rather not argue about it now.
+
+> I think it would be better to do one of the following:
+> (1) Mandate Program_Error when allocating any tasks; or
+> (2) Mandate the termination semantics of U_D (that is, none).
+
+I think we should keep it as is, or else do (1).
+I really don't like (2), because I want to be able to change the semantics in a
+future Ada.
+
+> In case (1), I suspect that implementations would provide a way to
+> turn this behavior off (extensions mode, perhaps?). But that would not
+> cause a compatibility problem, and we could use any termination that we want.
+
+Right, that's my intent, whether we keep the AI as is, or change to (1).
+
+> For case (2), I can't see how this would be a problem with GNAT, since
+> it would be saying that tasks use the same semantics that access types
+> currently have. This would prevent us from doing better sometime in
+> the future, but I'm skeptical that that would ever happen anyway.
+>
+> I actually prefer (2), since I think that the termination problem has
+> little to do with subpools and everything to do with insufficient control
+> of tasks.
+> If we decide to fix that in the future, we ought to do it on all task
+> types, and not just for subpools. (That way, all parts of the task
+> manager can share the pain. ;-) In that case, there is no good reason
+> to disallow tasks now - the problem is with the definition of tasks,
+> not the way subpools deal with them.
+
+Can we compromise on (1)?
+
+> ====================
+>
+> In the discussion:
+>
+> Meanwhile, the "root part" of the subpool object type will be used by
+> the Ada implementation to implement and finalization for the subpools,
+> as well as managing the connection between subpools and their parent
+> pool. (The Ada implementation may also use the "root part" of the
+> storage pool for this purpose.)
+>
+> Not sure what "implement and finalization" means.
+
+I meant to delete "and". I can reword this.
+
+> ===================
+>
+> For some reason, you moved the "another way that subpools can be used"
+> from the !example into the !discussion under "use as a building
+> block". That section is specifically about ways to be implement pools
+> that do automatic reclamation; this is not so much as an example as an
+> attempt to show that the fancier features of AI-0111-2 are not really necessary.
+>
+> In any case, the "another way that subpools can be used" has nothing
+> to do with using this subpools construct to build more complex memory management.
+> I could imagine putting both things into the !example section, but
+> random uses of this construct definitely do not belong in the
+> !discussion (which is supposed to be about technical issues with the
+> proposal).
+
+OK, I'll put it back the way it was.
+
+> ===================
+>
+> That's it. (Enough for sure.)
+
+Thanks again for the review.
+
+****************************************************************
+
+From: Jean-Pierre Rosen
+Sent: Tuesday, April 12, 2011 9:03 AM
+
+> I have no strong feeling either way. It doesn't change the semantics,
+> so lets hear from others, and take the majority opinion. So far:
+> Robert and I like it without the "with", Randy wants to put the "with"
+> back in.
+>
+> Does anybody else care?
+
+I tend to repeat "with" on children (and I have an AdaControl rule to that
+effect), but that's not a strong feeling either. Hmmm... I'd say that given that
+some people read the RM on paper, it might be a good idea to repeat it. There is
+no "goto parent declaration" right click on paper ;-)
+
+****************************************************************
+
+From: John Barnes
+Sent: Tuesday, April 12, 2011 10:29 AM
+
+> My personal style is to avoid optional with clauses.
+> I suspect that's the RM style, too, given that I wrote large parts of
+> it. On the other hand (sorry, John), maybe it never came up in the RM
+> before.
+
+Rhubarb!
+
+>
+> I have no strong feeling either way. It doesn't change the semantics,
+> so lets hear from others, and take the majority opinion. So far:
+> Robert and I like it without the "with", Randy wants to put the "with"
+> back in.
+>
+> Does anybody else care?
+
+I think it's better without spurious with.
+
+****************************************************************
+
+From: Ed Schonberg
+Sent: Tuesday, April 12, 2011 11:00 AM
+
+Our in-house style is to omit the with on children units, and there is a warning
+mode to flag redundant with-clauses (and redundant use clauses as well). I'm
+happy to leave them out as well in the RM.
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Tuesday, April 12, 2011 1:50 PM
+
+...
+> And I guess I need a few answers from you, Randy (see below) before
+> producing the new one.
+
+OK, see below.
+
+> > You changed the wording of 4.8(3/1) from:
+> >
+> > A *subpool_handle*_name is expected to be of any descendant of
+> > System.Storage_Pools.Subpools.Subpool_Handle, the type used to
+> > identify a subpool, defined in the language-defined package
+> > System.Storage_Pools.Subpools (see 13.11.4).
+> >
+> > to
+> >
+> > The expected type for a *subpool_handle*_name is Subpool_Handle, the type
+> > used to identify a subpool, declared package System.Storage_Pools.Subpools
+> > (see 13.11.4).
+> >
+> > This eliminates the possibility to derive a type from Subpool_Handle
+> > in the package for some user-written pool type. We previously
+> > decided that this makes using a subpool-supporting pool much easier,
+> > and thus we reworded this rule to allow derived types. (As we all
+> > know, a subtype is not equivalent to a derived type, as no operators come
+> > along.) Note that we did this in the example (haven't seen if you
+> > changed that or not).
+> >
+> > Did you do this intentionally (and if so, why - you didn't mention
+> > it anywhere)?? Or were you just trying to reword this and lost an
+> > intended capability?
+>
+> Yes, I did it intentionally. I thought it made sense for a client
+> subpool to derive from Root_Subpool; deriving from Subpool_Handle
+> seemed weird to me.
+>
+> The example uses a "renaming" subtype, and I didn't change that.
+>
+> I'm happy to put it back the way it was. No harm in allowing derived
+> _Handle types.
+
+It should be noted that I originally had this your way (see versions /02 and
+/03), but I was asked to change it in version /04 at the Fairfax ARG meeting.
+
+...
+> > ===================
+> >
+> > You changed the exception description for Set_Pool_of_Subpool from:
+> > -- Raises Program_Error if the Pool has already been set for Subpool
+> > -- since the last explicit finalization (if any) of the subpool.
+> > to:
+> > -- Raises Program_Error if the Pool already belongs to a pool.
+>
+> I changed this because there's no definition of what "explicit finalization"
+> means. A call to Finalize(My_Subpool)?
+>
+> I added text to Unchecked_Deallocate_Subpool: "and it no longer
+> belongs to any pool", which I think is what is intended. I can add
+> text to Create_Subpool and Set_Pool_of_Subpool to further clarify
+> (they say the right thing, except they don't use the word "belong").
+
+That should help.
+
+> > Three problems with this: first, I can't find any definition of when
+> > a subpool "belongs" to a pool; the only use of the term in normative
+> > wording is in the allocator check, which hardly could be a normative definition.
+>
+> OK, I'll try to complete that definition as above.
+
+Yes, and note that this was my mistake originally, you just copied it.
+
+> > Second, there is nothing named Pool here; perhaps you meant Subpool??.
+>
+> Yes.
+>
+> > Third, there is no other text which says that this "belongs" state
+> > is reset when the subpool is finalized -- that surely needs to be
+> > said normatively.
+>
+> I added that under Unchecked_Deallocate_Subpool.
+
+What about when the subpool is finalized some other way? Or did you include that
+under Unchecked_Deallocate_Subpool too? (Seems weird, but possible.)
+
+> > Similarly, a lot of the normative wording for Deallocate_Subpool has
+> > disappeared (why?). Specifically: "..., and destroy the subpool.
+>
+> I didn't know what "destroy the subpool" means. I don't think it
+> really means anything -- you can reuse the pool via
+> Set_Pool_of_Subpool. So I didn't think this added any particular
+> semantics, so I deleted it. (The interesting semantics here has to do
+> with "belong" -- at any given time, a subpool either belongs to some
+> pool, or not, and we need to clarify which operations change that
+> state).
+
+OK.
+
+> >... The subpool
+> > handle is set to null after this call." Where did this go?? You
+> >added "Unchecked_Deallocate_Subpool calls this", but surely it can be
+> >called directly, too, and if it is the subpool still has to be set to
+> >null (at the very least, the option has to exist should the subpool
+> >object be allocated from the heap). My preference is for this to be
+> >a requirement on the Deallocate_Subpool implementation (that's what
+> >I had here), as the checking for allocators depends on this, and it
+> >is best to treat anything that violates this as erroneous.
+>
+> Unchecked_Deallocate_Subpool sets it to null (already true in the
+> previous version of the AI).
+> Unchecked_Deallocation of a subpool sets it to null (that's Ada 83
+> semantics!).
+>
+> So I didn't see any need for Deallocate_Subpool to set also it to null.
+> Deallocate_Subpool would not normally be called directly.
+>
+> To me, it really seems weird to trust the programmer of
+> Deallocate_Subpool to set it to null. And even wierder to do it
+> twice.
+
+Well, I always do it everywhere. Even in the generated code for
+Unchecked_Deallocation, both the thunk and the call to the thunk set it to null.
+(That's probably a bug, but it makes my approach clear... :-) So I don't find
+this weird, I find it to be defensive programming. And see the next paragraph...
+
+> I think the language rules already make it clear that dereferencing
+> dangling Subpool_Handles is erroneous, and that's true whether or not
+> any of these operations null-out things.
+
+I'm at least as worried about cases where the subpool object is *not*
+deallocated, so the handle still points at a valid piece of memory. (As in the
+example pool.) In that case, a direct call to Deallocate_Subpool is still
+supposed to null out the handle.
+
+...
+> > ======================
+> >
+> > The Bounded Error
+> >
+> > I'm a bit worried about this error. You talked about relaxing the
+> > "restriction" in the future, but I don't see how that will work. If
+> > an implementation has just raised Program_Error for any contained
+> > tasks, there is no future problem.
+> >
+> > But if the implementation allows the allocator, the termination
+> > semantics are then implementation-defined. Since the same semantics
+> > as U_D are easy, I suspect many implementations will do that. But
+> > then if we want to apply "better" (different) semantics in the
+> > future, that would break any code that depends on the
+> > implementation-defined semantics.
+> >
+> > Thus, we'll never be able to change this Bounded Error in the future
+> > (unless no one supports tasks here, which I doubt will happen,
+> > especially if my predictions about multicore come true).
+>
+> My intention is that GNAT will initially raise Program_Error.
+> Later, when we get a chance to study the runtimes in more depth we
+> might do something else, under an option.
+> I'm not yet sure what "something else" is, and I'd rather not argue
+> about it now.
+>
+> > I think it would be better to do one of the following:
+> > (1) Mandate Program_Error when allocating any tasks; or
+> > (2) Mandate the termination semantics of U_D (that is, none).
+>
+> I think we should keep it as is, or else do (1).
+> I really don't like (2), because I want to be able to change the
+> semantics in a future Ada.
+>
+> > In case (1), I suspect that implementations would provide a way to
+> > turn this behavior off (extensions mode, perhaps?). But that would
+> > not cause a compatibility problem, and we could use any termination
+> > that we want.
+>
+> Right, that's my intent, whether we keep the AI as is, or change to
+> (1).
+>
+> > For case (2), I can't see how this would be a problem with GNAT,
+> > since it would be saying that tasks use the same semantics that
+> > access types currently have. This would prevent us from doing better
+> > sometime in the future, but I'm skeptical that that would ever happen anyway.
+> >
+> > I actually prefer (2), since I think that the termination problem
+> > has little to do with subpools and everything to do with
+> > insufficient control of tasks.
+> > If we decide to fix that in the future, we ought to do it on all
+> > task types, and not just for subpools. (That way, all parts of the
+> > task manager can share the pain. ;-) In that case, there is no good
+> > reason to disallow tasks now - the problem is with the definition of
+> > tasks, not the way subpools deal with them.
+>
+> Can we compromise on (1)?
+
+I would prefer that to the bounded error. The reason is that it would be a lot
+easier to *not* raise Program_Error.
+
+For Janus/Ada at least, doing nothing at all would provide (2) - since (2) is
+exactly how tasks in access types work today. Raising Program_Error would
+require adding a new operation to the task supervisor to raise Program_Error if
+the activation list is not empty. This is not that hard to do, but since it is
+infinitely more work than doing nothing, I can't imagine doing it if given a
+choice. But this is not the semantics you want.
+
+As I've said, I think the problem here is not with the subpools, but rather that
+tasks don't terminate immediately when completed. I suspect that we would be
+better off fixing that problem directly (probably with an aspect of a task type)
+rather than worrying about termination in any specific case. So I don't think
+(2) is a problem.
+
+But in any case we'll have a long time to think about it.
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Tuesday, April 12, 2011 2:05 PM
+
+> Legality Rules
+
+> A descendant of Root_Storage_Pool_with_Subpools shall not override
+> Allocate.
+
+In thinking about this rule this morning, it began to bother me.
+
+I can't speak for other compilers, but Janus/Ada uses the normal derivation
+mechanisms to create descendants of storage pools. And these mechanisms are
+fiendishly complex!
+
+Moreover, Ada has no rules currently like "shall not override". So this would be
+a totally one-off check stuck into a complex set of rules. And direct
+implementation would be painful, since we'd have to write a search to find out
+if something is a descendant of a particular Allocate subprogram (that doesn't
+follow). Probably the easiest way to implement this check would be to stick a
+"do_not_override" bit into the symbol table - but that is weird for one-time
+use.
+
+Finally, if this ("shall not override" is a good idea, it seems odd to allow it
+here but not let users define such routines in their packages.
+
+So I'm wondering whether we should define an aspect to this effect, and then use
+it so that this rule becomes automatically enforced. Say "Final". So if you have
+a routine defined:
+
+ procedure Allocate (Me : A_Pool; ...)
+ with Final;
+
+then overriding this routine is prohibited. Having such an aspect would justify
+the "do_not_override" symboltable bit, and would let it be used when
+appropriate.
+
+Thoughts??
+
+****************************************************************
+
+From: Bob Duff
+Sent: Thursday, April 21, 2011 10:56 PM
+
+> One more comment:
+>
+> > Legality Rules
+>
+> > A descendant of Root_Storage_Pool_with_Subpools shall not override
+> > Allocate.
+>
+> In thinking about this rule this morning, it began to bother me.
+
+It bothers me, too.
+
+> I can't speak for other compilers, but Janus/Ada uses the normal
+> derivation mechanisms to create descendants of storage pools. And
+> these mechanisms are fiendishly complex!
+>
+> Moreover, Ada has no rules currently like "shall not override". So
+> this would be a totally one-off check stuck into a complex set of
+> rules. And direct implementation would be painful, since we'd have to
+> write a search to find out if something is a descendant of a
+> particular Allocate subprogram (that doesn't follow). Probably the
+> easiest way to implement this check would be to stick a
+> "do_not_override" bit into the symbol table - but that is weird for one-time use.
+>
+> Finally, if this ("shall not override" is a good idea, it seems odd to
+> allow it here but not let users define such routines in their packages.
+>
+> So I'm wondering whether we should define an aspect to this effect,
+> and then use it so that this rule becomes automatically enforced. Say
+> "Final". So if you have a routine defined:
+>
+> procedure Allocate (Me : A_Pool; ...)
+> with Final;
+>
+> then overriding this routine is prohibited. Having such an aspect
+> would justify the "do_not_override" symboltable bit, and would let it
+> be used when appropriate.
+>
+> Thoughts??
+
+Well, "with Final" may well be a good idea, but I don't think we should be
+adding a whole new feature at this point. I agree the current rule requires a
+"one-off" check in the compiler. But clearly it's no harder to implement the
+one-off rule than a proper feature.
+
+I'd be happy to remove this kludgy rule, and just say that you're not expected
+to override it, and if you do, you get what the rules say you get.uuuu
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Tuesday, April 26, 2011 1:37 AM
+
+> Well, "with Final" may well be a good idea, but I don't think we
+> should be adding a whole new feature at this point. I agree the
+> current rule requires a "one-off" check in the compiler. But clearly
+> it's no harder to implement the one-off rule than a proper feature.
+
+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.
+
+****************************************************************
+
+From: Brad Moore
+Sent: Thursday, April 14, 2011 2:09 AM
+
+Thanks for the rewrite, having given more thought, and more experimentation, I
+now believe this proposal is considerably better than my -4 proposal, and
+believe this proposal is good to go forward with, although I do have some minor
+comments, questions, and suggestions.
+
+Incidentally, I have just released today a major rewrite of Deepend to use this
+proposal (as best as I can for Ada 2005), that is written 100% in Ada.
+
+The main compatibility difference between Ada 2005 and Ada 2012 is the use of an
+in out parameter for a function call, and I had to use GNAT precondition and
+postcondition pragmas instead of Pre and Post.
+
+> !problem
+>
+> This is exactly as safe as reclaiming the objects one at a time with
+> Unchecked_Deallocation (in that dangling pointers can be created).
+> However, this approach adds flexiblity in storage management (as the
+> memory can be reclaimed with a single operation), and can be used as a
+> building block for safer allocations.
+
+I thought you wanted to change the wording here about "exactly as safe", as
+subpools are actually a lot safer.
+
+> !wording
+>
+> 13.11.4 Storage Subpools
+>
+> package System.Storage_Pools.Subpools is
+> pragma Preelaborate (Subpools);
+>
+> procedure Set_Pool_of_Subpool(Subpool : not null Subpool_Handle;
+> To : in out Root_Storage_Pool_with_Subpools'Class);
+> -- Set the Pool for a newly created subpool or a subpool that
+> -- is being reused after a call to Unchecked_Deallocate_Subpool.
+> -- This is intended to be called from Create_Subpool or similar
+> -- subpool constructors.
+> -- Raises Program_Error if the Pool already belongs to a pool.
+
+This should be "if the {subp}[P]ool already belongs to a pool."
+
+> procedure Allocate_From_Subpool(
+> Pool : in out Root_Storage_Pool_with_Subpools;
+> Storage_Address : out Address;
+> Size_In_Storage_Elements : in Storage_Elements.Storage_Count;
+> Alignment : in Storage_Elements.Storage_Count;
+> Subpool : not null Subpool_Handle) is abstract
+> with Pre'Class => Pool_of_Subpool(Subpool) = Pool'Access;
+> -- Allocate space from specified subpool.
+> -- [Editor's note: The precondition is as described in AI05-0145-2 and
+> -- AI05-0183-1. It could be omitted if necessary.]
+>
+> procedure Deallocate_Subpool(
+> Pool : in out Root_Storage_Pool_with_Subpools;
+> Subpool : in out Subpool_Handle) is abstract
+> with Pre'Class => Pool_of_Subpool(Subpool) = Pool'Access;
+> -- Deallocate the space for all of the objects allocated from the
+> -- specified subpool. Unchecked_Deallocate_Subpool calls this.
+
+By "Deallocate the space", is it acceptable to not actually deallocate space,
+but make the space available for reuse?
+
+In my new Deepend version, this function is invoked by two separate calls. I
+have a primitive Unchecked_Deallocate_Subpool, which sets a flag in the subpool
+to indicate full deallocation of the subpool, then it calls
+Ada.Unchecked_Deallocate_Subpool, which then calls Deallocate_Subpool, and
+deallocates all the storage. This is a convenience primitive so that clients
+dont have to with Ada.Unchecked_Deallocation, and can do everything using the
+primitives of the subpool.
+
+I also have a Unchecked_Deallocate_Objects, which sets a flag in the subpool to
+indicate only make the allocated space available for reuse, then calls
+Ada.Unchecked_Deallocate_Subpool, which then calls Deallocate_Subpool, which
+then makes the space reusable, then clears the flag in the subpool, so that a
+subsequent call to Ada.Unchecked_Deallocate_Subpool will work as expected.
+
+This raises another question. Why can't Unchecked_Deallocate_Subpool be a
+primitive of Root_Storage_Pool_With_Subpools? My understanding is that this was
+made a separate library unit because people were worried that someone might
+override the primitive and not call the ancestor version of the primitive. Now
+that we have these new fandangled postconditions, I think this could be
+reasonably enforced by by having a postcondition on the call.
+
+If we had the function;
+
+ function Objects_Need_Finalization
+ (Subpool : Subpool_Handle) return Boolean;
+ -- Returns true if there are objects allocated from the pool that have
+ -- not been deallocated and need finalization.
+
+then we could have the primitive;
+
+ procedure Unchecked_Deallocate_Subpool
+ (Subpool : in out Subpool_Handle)
+ with Post'Class => (not Objects_Need_Finalization (Subpool));
+
+And regardless whether it is deemed a good idea to make
+Unchecked_Deallocate_Subpool a primitive, Could we add the
+Objects_Need_Finalization call? I would use that in postconditions in my Deepend
+pool, if it was available. It would make available another useful bit of
+information about the implementions finalization that I think should be easy to
+implement.
+
+> AARM Reason:
+> This check (and its static counterpart) ensures that the type of the allocated
+> objects exist at least as long as the storage pool object, so that the subpools
+> are finalized (which finalizes any remaining allocated objects) before the type
+> of the objects ceases to exist. The access type itself will cease to exist before
+> the storage pool.
+
+Before the storage pool what? Is finalized?
+
+> A call to Subpools.Allocate(P, Addr, Size, Align) does the following:
+>
+> Allocate_From_Subpool
+> (Root_Storage_Pool_with_Subpools'Class(P),
+> Addr, Size, Align,
+> Subpool => Default_Subpool_for_Pool
+> (Root_Storage_Pool_with_Subpools'Class(P)));
+>
+
+I thought this wasn't true anymore now that we are supporting the two
+implementation models.
+
+> 13.11.5 Subpool Reclamation
+>
+> The following language-defined library procedure exists:
+>
+> procedure Ada.Unchecked_Deallocate_Subpool
+> (Subpool : in out
+> System.Storage_Pools.Subpools.Subpool_Handle);
+>
+> A subpool may be explicitly deallocated using Unchecked_Deallocate_Subpool.
+>
+> If Subpool is null, a call on Unchecked_Deallocate_Subpool has no
+> effect. Otherwise, the subpool is finalized, and it no longer belongs
+> to any pool. Finally, Subpool is set to null.
+
+I want Deallocate_Subpool to have the responsibility of setting Subpool to null.
+(Which is how I thought it worked before your update) As I mentioned, In
+Deepend, I have two modes for Deallocate_Subpool, one that sets the Subpool to
+null, and one that leaves it as it was, allowing more allocations from the
+subpool reusing the same storage space.
+
+> Unchecked_Deallocate_Subpool is a potentially blocking operation (see 9.5.1).
+
+Is this still true, if we are disallowing the allocation of tasks?
+
+> !discussion
+>
+> Meanwhile, the "root part" of the subpool object type will be used by
+> the Ada implementation to implement and finalization for the subpools,
+> implement *any* finalization?
+> as well as managing the connection between subpools and their parent
+
+managing => manage
+
+> DANGLING SUBPOOL HANDLES
+>
+> However, those rules just mean that execution may become erroneous. To
+> help prevent that, we've taken several measures:
+>
+> * We null the provided subpool handle when calling Unchecked_Deallocate_Subpool
+> to minimize the cases of dangling subpool handles.
+
+I want the subpool programmer to have this responsibility as I mentioned above.
+There may be cases where the subpool handle is still alive and useful after the
+call.
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Thursday, April 14, 2011 5:28 PM
+
+...
+> > procedure Deallocate_Subpool(
+> > Pool : in out Root_Storage_Pool_with_Subpools;
+> > Subpool : in out Subpool_Handle) is abstract
+> > with Pre'Class => Pool_of_Subpool(Subpool) = Pool'Access;
+> > -- Deallocate the space for all of the objects allocated from the
+> > -- specified subpool. Unchecked_Deallocate_Subpool calls this.
+>
+> By "Deallocate the space", is it acceptable to not actually deallocate
+> space, but make the space available for reuse?
+
+Pool writers can do whatever they want with these routines. This is the
+description of the high-level view of the routine (the one clients see), but do
+whatever makes sense under the covers.
+
+> In my new Deepend version, this function is invoked by two separate
+> calls. I have a primitive Unchecked_Deallocate_Subpool, which sets a
+> flag in the subpool to indicate full deallocation of the subpool, then
+> it calls Ada.Unchecked_Deallocate_Subpool, which then calls
+> Deallocate_Subpool, and deallocates all the storage.
+> This is a convenience primitive so that clients dont have to with
+> Ada.Unchecked_Deallocation, and can do everything using the primitives
+> of the subpool.
+>
+> I also have a Unchecked_Deallocate_Objects, which sets a flag in the
+> subpool to indicate only make the allocated space available for reuse,
+> then calls Ada.Unchecked_Deallocate_Subpool, which then calls
+> Deallocate_Subpool, which then makes the space reusable, then clears
+> the flag in the subpool, so that a subsequent call to
+> Ada.Unchecked_Deallocate_Subpool will work as expected.
+
+This seems overly complex to me. If reuse makes sense, you'll almost always want
+to do it, so why separate it? And if it doesn't make sense, having two routines
+just makes the interface harder to use.
+
+> This raises another question. Why can't Unchecked_Deallocate_Subpool
+> be a primitive of Root_Storage_Pool_With_Subpools?
+> My understanding is that this was made a separate library unit because
+> people were worried that someone might override the primitive and not
+> call the ancestor version of the primitive. Now that we have these new
+> fandangled postconditions, I think this could be reasonably enforced
+> by by having a postcondition on the call.
+
+A postcondition is a lousy way to do this. If Bob keeps the rule about not
+allowing overriding of Allocate, it would make some sense to do the same thing
+here. (That is, put this into the package, but not allow any overriding.)
+
+But that has a negative effect, it would complicate the package for all of
+clients, pool writers, and implementers. The problem is that there is a mix of
+routines that pool writer are supposed to write and implementers are supposed to
+write. It would be better for these to be in separate packages. I didn't quite
+succeed in that separation (Pool_from_Subpool and Set_Pool_for_Subpool really
+don't belong here), but at least clients don't need to know about those. Not
+sure what is best here (Pool_from_Subpool is a routine created by the
+implementation to be used by the pool writer; Allocate_from_Subpool is a routine
+created by the pool writer to be used by the implementation; Create_Subpool is a
+routine created by the pool writer to be used by the client;
+Unchecked_Deallocate_Subpool is a routine created by the implementation to be
+used by the client. Yikes!)
+
+> If we had the function;
+>
+> function Objects_Need_Finalization
+> (Subpool : Subpool_Handle) return Boolean;
+> -- Returns true if there are objects allocated from the pool that have
+> -- not been deallocated and need finalization.
+...
+> And regardless whether it is deemed a good idea to make
+> Unchecked_Deallocate_Subpool a primitive, Could we add the
+> Objects_Need_Finalization call?
+
+It surely would add additional complications (being another routine for client
+use, provided by the implementation, that should not be overridden). I'm not
+sure it really helps anything (in the absence of a "Final" aspect, anyway), as a
+pool can break the postcondition by overriding this routine, and you'll end up
+with the same unusable pool.
+
+> > AARM Reason:
+> > This check (and its static counterpart) ensures that the type of the allocated
+> > objects exist at least as long as the storage pool object, so that the subpools
+> > are finalized (which finalizes any remaining allocated objects) before the type
+> > of the objects ceases to exist. The access type itself will cease to exist before
+> > the storage pool.
+> >
+> Before the storage pool what? Is finalized?
+
+"...before the storage pool is finalized and ceases to exist."
+
+But I think "cease to exist" isn't quite right for the access type; I was trying
+to talk about when the access type's collection is finalized. (Since Bob has now
+made that a general term, we can sanely talk about that again. Yea.)
+
+The storage pool object and the access type have to be in the same master, and
+the pool has to be declared before the access type is frozen, which means that
+the access type's collection has to be finalized before the pool object is
+finalized. The implementation permission allows finalizing the collection when
+the pool is finalized rather than when the access type is; that won't make much
+difference in general.
+
+> > A call to Subpools.Allocate(P, Addr, Size, Align) does the following:
+> >
+> > Allocate_From_Subpool
+> > (Root_Storage_Pool_with_Subpools'Class(P),
+> > Addr, Size, Align,
+> > Subpool => Default_Subpool_for_Pool
+> > (Root_Storage_Pool_with_Subpools'Class(P)));
+> >
+>
+> I thought this wasn't true anymore now that we are supporting the two
+> implementation models.
+
+In Bob's version, it always does this, and cannot be overridden. That's how the
+call Allocate implementation model works.
+
+...
+> > If Subpool is null, a call on Unchecked_Deallocate_Subpool has no
+> > effect. Otherwise, the subpool is finalized, and it no longer
+> > belongs to any pool. Finally, Subpool is set to null.
+> >
+> I want Deallocate_Subpool to have the responsibility of setting
+> Subpool to null.
+> (Which is how I thought it worked before your update) As I mentioned,
+> In Deepend, I have two modes for Deallocate_Subpool, one that sets the
+> Subpool to null, and one that leaves it as it was, allowing more
+> allocations from the subpool reusing the same storage space.
+
+You would need to recreate the subpool in order to do that, so you shouldn't
+reuse the same handle (even though it might actually turn out to be the same
+handle).
+
+Specifically, when you deallocate a subpool, that also severs the connection to
+the pool. This is critical in order to avoid problems with use of dangling, not
+open subpools. In order to recreate that connection, you need to create the
+subpool, and that will necessarily give you a subpool handle.
+
+Note that the implementation of the pool can reuse the subpool objects (as in
+the Mark/Release example), but you're not supposed to reuse the handles.
+
+> > Unchecked_Deallocate_Subpool is a potentially blocking operation
+> > (see 9.5.1).
+>
+> Is this still true, if we are disallowing the allocation of tasks?
+
+Dunno. That's up to Bob. (It makes some sense for this to be the case to avoid
+future incompatibility when we do allow tasks.)
+
+...
+> > DANGLING SUBPOOL HANDLES
+> >
+> > However, those rules just mean that execution may become erroneous.
+> > To help prevent that, we've taken several measures:
+> >
+> > * We null the provided subpool handle when calling Unchecked_Deallocate_Subpool
+> > to minimize the cases of dangling subpool handles.
+> >
+> I want the subpool programmer to have this responsibility as I
+> mentioned above. There may be cases where the subpool handle is still
+> alive and useful after the call.
+
+So you want subpools to be unsafe? :-)
+
+Specifically, once a subpool has been deallocated, it cannot be used further
+without being recreated. (That's necessary so that the implementation can get a
+chance to clean and reinitialize data structures for use; it shouldn't do that
+otherwise as the subpool object might be freed as well, and it is possible that
+these data structures are linked to other implementation structures [for
+instance, a finalization list].)
+
+As I noted previously, it is perfectly fine to reuse subpool objects, but not to
+reuse subpool handles. (As a practical matter, the pool writer could arrange for
+the handles to continue to have the same values, by just reusing the subpool
+objects, but that is definitely not an intended use case.)
+
+****************************************************************
+
+From: Brad Moore
+Sent: Friday, April 15, 2011 12:00 AM
+
+> > In my new Deepend version, this function is invoked by two
+> > separate calls. I have a primitive
+> > Unchecked_Deallocate_Subpool, which sets a flag in the
+> > subpool to indicate full deallocation of the subpool, then it
+> > calls Ada.Unchecked_Deallocate_Subpool, which then calls
+> > Deallocate_Subpool, and deallocates all the storage.
+> > This is a convenience primitive so that clients dont have to
+> > with Ada.Unchecked_Deallocation, and can do everything using
+> > the primitives of the subpool.
+> >
+> > I also have a Unchecked_Deallocate_Objects, which sets a flag
+> > in the subpool to indicate only make the allocated space
+> > available for reuse, then calls
+> > Ada.Unchecked_Deallocate_Subpool, which then calls
+> > Deallocate_Subpool, which then makes the space reusable, then
+> > clears the flag in the subpool, so that a subsequent call to
+> > Ada.Unchecked_Deallocate_Subpool will work as expected.
+>
+> This seems overly complex to me. If reuse makes sense, you'll almost always
+> want to do it, so why separate it? And if it doesn't make sense, having two
+> routines just makes the interface harder to use.
+
+In my pool, the intention is only one task can allocate from a particular
+subpool. The idea is that the subpool allocation code can be simple and fast,
+and ideally not involve synchronization code or protected objects.
+
+When a task completes, there is no need for the subpool, so that is when you
+would want to call Unchecked_Deallocate_Subpool. On the other hand, the task
+might involve several stages of processing, where moving to the next stage means
+no need for objects allocated from the previous stage. In that case, that is an
+example of where you would want to call Unchecked_Deallocate_Objects.
+
+I don't see this as overly complex from the user perspective. Having to set and
+store this flag in my implementation is an annoying bit of complexity that
+arises because I don't have the primitives I need, so I am having to shoehorn
+the one primitive I do have onto two different behaviors. I suppose in the
+multi-stage example, I could just create new subpools when I get to the next
+stage of processing, but I don't want to be forced to do that because it likely
+would be less efficient as I would be having to deallocate subpools, and then
+reallocate them.
+
+One feature of the new version of Deepend that I like is what I call a
+scoped_subtype_handle. This is a controlled type that has the subtype handle as
+a discriminant. A version of Create_Subpool returns this type, so that when the
+subpool is declared in a nested scope, it will be guaranteed to call
+Unchecked_Deallocate_Subpool when it goes out of scope. This is safer than
+having the user have to explicitly make a call to U_D_S before returning from
+the nested scope, which is error prone due to possible early exits, or
+exceptions being raised etc. Another nice feature of this, is that the subtype
+handle is a discriminant and cant be passed to U_D_S directly, because it is not
+a variable, which makes the client have to go out of his way to make the call,
+which would lead to erroneous behavior when the Scoped_Subpool_Handle is
+finalized.
+
+This is another reason why I don't want the subpool handle to change when I want
+to use the Unchecked_Deallocate_Objects functionality.
+
+Ideally, there would be a primitive Unchecked_Deallocate_Objects in the root
+Subpools package that does object finalization, but ensures these implementation
+structures are left in a state where further allocations could be made. This
+call would not dispatch back or call Deallocate_Subpool. If that were available,
+then I wouldn't have to shoehorn two functionalities into one call, and it would
+simplify my pool implementation, as well as make the code cleaner.
+
+> > This raises another question. Why can't
+> > Unchecked_Deallocate_Subpool be a primitive of
+> > Root_Storage_Pool_With_Subpools?
+> > My understanding is that this was made a separate library
+> > unit because people were worried that someone might override
+> > the primitive and not call the ancestor version of the
+> > primitive. Now that we have these new fandangled
+> > postconditions, I think this could be reasonably enforced by
+> > by having a postcondition on the call.
+>
+> A postcondition is a lousy way to do this. If Bob keeps the rule about not
+> allowing overriding of Allocate, it would make some sense to do the same
+> thing here. (That is, put this into the package, but not allow any
+> overriding.)
+
+I agree with this. In that case, Unchecked_Deallocate_Objects could
+also have the same treatment, and one wouldn't be allowed to override
+that routine either.
+
+> But that has a negative effect, it would complicate the package for all of
+> clients, pool writers, and implementers. The problem is that there is a mix
+> of routines that pool writer are supposed to write and implementers are
+> supposed to write. It would be better for these to be in separate packages.
+
+I disagree.
+I think it is a positive effect. Having all the routines you need in one place
+is a good thing. Having all but one of these in the same place, but having to go
+to a completely different place for one call to me is more of a negative
+effect, and potentially more confusing to users. It's really the pool
+implementor that sees most of these routines, and they can be hidden in the
+private part of the pool implementors package. I'm not too worried about pool
+implementors getting confused. They only have to write the package once, and
+seeing the example in the RM should provide a good means to show how it can be
+done. The U_D_S call however is in a different place, and it impacts the clients
+usage, not the subpool writers usage.
+
+> > If we had the function;
+> >
+> > function Objects_Need_Finalization
+> > (Subpool : Subpool_Handle) return Boolean;
+> > -- Returns true if there are objects allocated from the pool that have
+> > -- not been deallocated and need finalization....
+> > And regardless whether it is deemed a good idea to make
+> > Unchecked_Deallocate_Subpool a primitive, Could we add the
+> > Objects_Need_Finalization call?
+>
+> It surely would add additional complications (being another routine for
+> client use, provided by the implementation, that should not be
+> overridden).I'm not sure it really helps anything (in the absence of a "Final" aspect,
+> anyway), as a pool can break the postcondition by overriding this routine,
+> and you'll end up with the same unusable pool.
+
+I think if Unchecked_Deallocate_Subpools (and Unchecked_Deallocate_Objects)
+were not overridable, then I wouldn't need this primitive.
+
+> The storage pool object and the access type have to be in the same master,
+> and the pool has to be declared before the access type is frozen, which
+> means that the access type's collection has to be finalized before the pool
+> object is finalized. The implementation permission allows finalizing the
+> collection when the pool is finalized rather than when the access type is;
+> that won't make much difference in general.
+
+No, but on this topic, one thing that is critical is that when the pool is
+finalized, the finalization of the pool should not make calls to U_D_S to
+deallocate the subpools.
+
+I see this as a mistake pool implementors will run into, as the pool has a list
+of subpools handles that need to be deallocated. The first thought will be to
+call U_D_S on each of these.
+
+I just realized I have this bug myself. The problem is that in my Pool object, I
+have a list of subpools that is stored in a protected object.
+
+When the pool is finalized, I wanted a protected operation that frees all the
+subpools.
+
+The initial approach I took was to call U_D_S for each of these. However, that
+leaves the P.O. and then dispatches back to a routine that likely needs to
+modify the pool object's subpool list. It can't however because the P.O. is
+already locked out, which leads to a deadlock. This is probably a good reason
+why U_D_S should be a potentially blocking operation.
+
+What I am getting at is that I think maybe there should be some wording in the
+RM to caution or disallow calling U_D_S during finalization of the pool. This
+shouldn't be needed anyway, since the objects will already have been finalized
+since the access type's collection will already have been finalized. Am I
+correct?
+
+...
+> > I want Deallocate_Subpool to have the responsibility of setting Subpool to
+> > null. (Which is how I thought it worked before your update) As I
+> > mentioned, In Deepend, I have two modes for
+> > Deallocate_Subpool, one that sets the Subpool to null, and
+> > one that leaves it as it was, allowing more allocations from
+> > the subpool reusing the same storage space.
+>
+> You would need to recreate the subpool in order to do that, so you shouldn't
+> reuse the same handle (even though it might actually turn out to be the same
+> handle).
+
+I explained above why I need to reuse the same handle, which would be quite
+difficult to enforce for a subpool that deallocates storage when Deallocate_Pool
+is called.
+
+I'm thinking that the ideal solution would be to have the two routines, U_D_S,
+and U_D_O. U_D_S would then clear the handle to null, as proposed, whereas U_D_O
+would leave the handle unchanged, and the subtype handle would be an in
+parameter instead of an in out parameter.
+
+> Specifically, when you deallocate a subpool, that also severs the connection
+> to the pool. This is critical in order to avoid problems with use of
+> dangling, not open subpools.
+
+Agreed. If I had a way to finalize objects without deallocating a subpool
+however, then that call wouldn't/shouldn't sever its connection to the pool, and
+there is no problem with dangling, not open subpools.
+
+...
+> > I want the subpool programmer to have this responsibility as
+> > I mentioned above. There may be cases where the subpool
+> > handle is still alive and useful after the call.
+>
+> So you want subpools to be unsafe? :-)
+>
+> Specifically, once a subpool has been deallocated, it cannot be
+> used further
+> without being recreated. (That's necessary so that the
+> implementation can
+> get a chance to clearn and reinitialize data structures for use; it
+> shouldn't do that otherwise as the subpool object might be freed
+> as well,
+> and it is possible that these data structures are linked to other
+> implementation structures [for instance, a finalization list].)
+
+Good point. I hadn't thought of that. However, U_D_O avoids these issues
+since subpools are not being deallocated.
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Friday, April 15, 2011 1:35 AM
+
+...
+> > > I also have a Unchecked_Deallocate_Objects, which sets a flag in
+> > > the subpool to indicate only make the allocated space available
+> > > for reuse, then calls Ada.Unchecked_Deallocate_Subpool, which then
+> > > calls Deallocate_Subpool, which then makes the space reusable,
+> > > then clears the flag in the subpool, so that a subsequent call to
+> > > Ada.Unchecked_Deallocate_Subpool will work as expected.
+> >
+> > This seems overly complex to me. If reuse makes sense, you'll almost
+> > always want to do it, so why separate it? And if it doesn't make
+> > sense, having two routines just makes the interface harder to use.
+>
+> In my pool, the intention is only one task can allocate from a
+> particular subpool. The idea is that the subpool allocation code can
+> be simple and fast, and ideally not involve synchronization code or
+> protected objects.
+>
+> When a task completes, there is no need for the subpool, so that is
+> when you would want to call Unchecked_Deallocate_Subpool.
+> On the other hand, the task might involve several stages of
+> processing, where moving to the next stage means no need for objects
+> allocated from the previous stage. In that case, that is an example of
+> where you would want to call Unchecked_Deallocate_Objects.
+>
+> I don't see this as overly complex from the user perspective.
+
+Maybe not, but the names of the routines are not helpful. With the names you
+have, I would expect to have to call both U_D_O and U_D_S to get rid of a
+subpool (first get rid of the objects, then the subpool), and that does not
+appear to be your intent.
+
+Unchecked_Deallocate_Objects_from_Subpool_but_Allow_Further_Use and
+Unchecked_Deallocate_Objects_from_Subpool_and_Destroy_It
+
+would be better, but a tad long. ;-)
+
+Part of the problem is your description. Whenever you deallocate an object, you
+are returning the storage to the pool. What the pool does with the storage is
+it's business.
+
+When you start talking about not freeing storage or returning storage to the
+"system", you confuse everyone.
+
+> Having to set and store this flag in my implementation is an annoying
+> bit of complexity that arises because I don't have the primitives I
+> need, so I am having to shoehorn the one primitive I do have onto two
+> different behaviors. I suppose in the multi-stage example, I could
+> just create new subpools when I get to the next stage of processing,
+> but I don't want to be forced to do that because it likely would be
+> less efficient as I would be having to deallocate subpools, and then
+> reallocate them.
+
+I don't see any reason that you would have deallocate a subpool if you don't
+want to. There is no requirement to make any of the low-level routines visible
+to clients (that's one reason for allowing derived subpool handles).
+
+It surely would be possible to build routines that did the effect of your U_D_O
+and U_D_S based on an underlying Deallocate_Subpool that does not destroy the
+subpool object, and then having an explicit routine to destroy the subpool
+object if that is desired.
+
+> One feature of the new version of Deepend that I like is what I call a
+> scoped_subtype_handle. This is a controlled type that has the subtype
+> handle as a discriminant. A version of Create_Subpool returns this
+> type, so that when the subpool is declared in a nested scope, it will
+> be guaranteed to call Unchecked_Deallocate_Subpool when it goes out of
+> scope.
+
+That seems reasonable. The discriminant seems to be a point in favor of getting
+rid of the "in out" parameter.
+
+Of course (since the handles can be copied all you want), you could put the
+handle into a component and use a routine like the container Reference routine
+to make it available to an allocator. That would be about the same amount of
+text, but is a bit more complex.
+
+...
+> Ideally, there would be a primitive
+> Unchecked_Deallocate_Objects in the root Subpools package that does
+> object finalization, but ensures these implementation structures are
+> left in a state where further allocations could be made. This call
+> would not dispatch back or call Deallocate_Subpool.
+
+The problem with that is that if you *don't* call Deallocate_Subpool, the pool
+will never get control to reuse the memory. (Recall that U_D_S and U_D_O aren't
+overridable.) The memory has to be returned to the pool somehow! U_D_O can't do
+it (it is written by the implementation and knows nothing about how
+Allocate_from_Subpool works). Even if all you need to do is set a flag, that has
+to be done by some other routine provided by the pool, not the implementation,
+and the intent is that routine is Deallocate_Subpool.
+
+If we were to add your U_D_O, we would have to add a parameter to
+Deallocate_Subpool to specify whether or not to destroy the subpool, or whether
+to reinitialize it. That was complexity I was trying to avoid, but perhaps that
+is really necessary.
+
+> If that were available, then I
+> wouldn't have to shoehorn two functionalities into one call, and it
+> would simplify my pool implementation, as well as make the code
+> cleaner.
+
+It wouldn't simplify your pool implementation, because you have call
+*something* in the pool as part of both U_D_S and U_D_O -- language-define
+routines can have no effect on the storage provided by your pool.
+
+...
+> > But that has a negative effect, it would complicate the package for
+> > all of clients, pool writers, and implementers.
+> > The problem is that there is a mix
+> > of routines that pool writer are supposed to write and implementers
+> > are supposed to write. It would be better for these to be in
+> > separate packages.
+>
+> I disagree.
+> I think it is a positive effect. Having all the routines you need in
+> one place is a good thing.
+
+Who is you?
+
+The package for the client shouldn't be bogged down with all of these
+implementation things.
+
+And the routines the client is supposed to call can't be overridden, so the
+client has to figure out the inherited routines that don't appear in the source.
+That is going to be a mess, because there are lots of routines the client ought
+not care about (Allocate_From_Subpool, Pool_from_Subpool, Set_Pool_of_Subpool,
+Deallocate_Subpool, etc.).
+
+We managed to avoid this with the example (the only routines declared in the
+spec are ones the client would care about), but that only works because U_D_S is
+a separate routine.
+
+Whether that will work in general is an interesting question. Probably the best
+way to use subpools is to make a totally separate client package with only the
+interesting operations exposed (the pool type, the subpool handle type, create
+subpools, etc.) But that will hardly every be able to be created just by the
+pool implementation, it will need to be a new package with a whole set of
+wrappers.
+
+> Having all but one of
+> these in the same place, but having to go to a completely different
+> place for one call to me is more of a negative effect, and potentially
+> more confusing to users.
+
+You are right about this.
+
+> It's really
+> the pool implementor that sees most of these routines, and they can be
+> hidden in the private part of the pool implementors package.
+
+Not really, in that U_D_S is not overridable, so the users will have to know
+about the inherited routines in order to use it (it won't be in the source!).
+And once they have to do that, whether the implementation "is hidden in the
+private part" is irrelevant - they'll see the entire set of routines that they
+don't need to use.
+
+> I'm not too worried about pool
+> implementors getting confused.
+> They only have to write the package once, and seeing the example in
+> the RM should provide a good means to show how it can be done. The
+> U_D_S call however is in a different place, and it impacts the clients
+> usage, not the subpool writers usage.
+
+Well, *I'm* confused trying to figure this out for the language. If it is that
+hard, you and Bob will be the only pool implementers, and that's not what we
+want.
+
+...
+> > The storage pool object and the access type have to be in the same
+> > master, and the pool has to be declared before the access type is
+> > frozen, which means that the access type's collection has to be
+> > finalized before the pool object is finalized. The implementation
+> > permission allows finalizing the collection when the pool is
+> > finalized rather than when the access type is; that won't make much
+> > difference in general.
+>
+> No, but on this topic, one thing that is critical is that when the
+> pool is finalized, the finalization of the pool should not make calls
+> to U_D_S to deallocate the subpools.
+
+The pool writer shouldn't be finalizing anything except his own memory. The
+language will take care of any contents -- that's the normal rule for a pool.
+Under *no* circumstances does the pool writer do anything to finalize objects
+allocated from his pool: that's always up to the client (U_D_S) and
+implementation.
+
+> I see this as a mistake pool implementors will run into, as the pool
+> has a list of subpools handles that need to be deallocated. The first
+> thought will be to call U_D_S on each of these.
+>
+> I just realized I have this bug myself. The problem is that in my Pool
+> object, I have a list of subpools that is stored in a protected
+> object.
+
+I would have said that's unlikely, but apparently, I'm already wrong. :-)
+
+> When the pool is finalized, I wanted a protected operation that frees
+> all the subpools.
+>
+> The initial approach I took was to call U_D_S for each of these. However,
+> that leaves the P.O. and then dispatches back to a routine that likely needs
+> to modify the pool object's subpool list. It can't however because the P.O. is
+> already locked out, which leads to a deadlock. This is probably a good reason
+> why U_D_S should be a potentially blocking operation.
+
+Pool writers never, ever call U_D_S. That's one reason why it wasn't in the pool
+package. :-)
+
+> What I am getting at is that I think maybe there should be some
+> wording in the RM to caution or disallow calling U_D_S during
+> finalization of the pool. This shouldn't be needed anyway, since the
+> objects will already have been finalized since the access type's
+> collection will already have been finalized. Am I correct?
+
+Right. The implementation could do that finalization as part of finalizing the
+pool, but it has to do it before calling the user's Finalize routine. And it is
+never the pool writer's job.
+
+...
+> I explained above why I need to reuse the same handle, which would be
+> quite difficult to enforce for a subpool that deallocates storage when
+> Deallocate_Pool is called.
+
+*Every* subpool deallocates storage when U_D_S or U_D_O is called. That *only*
+means that the storage is returned to the pool for reuse. You apparently mean
+something else by "deallocates storage".
+
+You always will need to call a routine like Deallocate_Subpool as part of U_D_S
+or U_D_O, else you could not reuse the storage (however that happens), and that
+totally defeats the purpose of the deallocation! But there is no requirement
+that Deallocate_Subpool actually deallocate the subpool object (in the sense of
+calling Unchecked_Deallocation on the subpool object) or any other memory
+(whatever that means).
+
+> I'm thinking that the ideal solution would be to have the two
+> routines, U_D_S, and U_D_O.
+> U_D_S would then clear the handle to null, as proposed, whereas U_D_O
+> would leave the handle unchanged, and the subtype handle would be an
+> in parameter instead of an in out parameter.
+>
+> > Specifically, when you deallocate a subpool, that also severs the
+> > connection to the pool. This is critical in order to avoid problems
+> > with use of dangling, not open subpools.
+>
+> Agreed. If I had a way to finalize objects without deallocating a
+> subpool however, then that call wouldn't/shouldn't sever its
+> connection to the pool, and there is no problem with dangling, not
+> open subpools.
+
+You're never required to "deallocate" a subpool, just that you are required to
+recreate (reinitialize) it before using it further. Look at the Mark/Release
+example; subpool objects there live forever. I'm certain that you could get the
+effect you want with the primitives that are defined in AI05-0111-3, the only
+question is whether it would be harder to use than necessary (I don't care that
+much how hard it is for the pool writer).
+
+****************************************************************
+
+From: Brad Moore
+Sent: Friday, April 15, 2011 9:55 AM
+
+> Maybe not, but the names of the routines are not helpful. With the
+> names you have, I would expect to have to call both U_D_O and U_D_S to
+> get rid of a subpool (first get rid of the objects, then the subpool),
+> and that does not appear to be your intent.
+>
+> Unchecked_Deallocate_Objects_from_Subpool_but_Allow_Further_Use and
+> Unchecked_Deallocate_Objects_from_Subpool_and_Destroy_It
+>
+> would be better, but a tad long. ;-)
+
+I see your point. U_D_O is not confusing by itself. U_D_S is where the confusion
+arises. I think it comes down to documentation. If its documented to deallocate
+all the objects and the subpool, it should be pretty clear.
+
+However I just realized it is trivially easy for me to recover the subpool
+handle even though Ada.U_D_S wants to set it to null. I can keep my current
+implementation pretty much the way it was.
+
+Therefore, I withdraw my comment about wanting U_D_O as a primitive of the root
+subpool. I also withdraw my request for Objects_Need_Finalization. I can make do
+without.
+
+I didn't like the subpool user having to go to Ada.U_D_S to deallocate the
+subpool, which is why I have a call in my pool called U_D_S. I think I should
+make that a renames of Ada.U_D_S (once that function actually exists and becomes
+part of the standard)
+
+This way, my subpool abstraction provides everything you need to work with the
+pool and subpools.
+
+I still think it might make sense to move Ada.U_D_S to the root subpool package,
+(and disallow overriding) It might encourage pool writers to create similar
+renames for the call, just as I plan to do with my pool. In the same way, I have
+also created a subtype_handle subtype in my pool which is a rename of the
+subtype_handle in the root subpool package, to make the package easier to use,
+which I suspect will be a technique commonly used.
+
+I also have the U_D_O call, which as I said before, ultimately calls Ada.U_D_S.
+
+>> It's really
+>> the pool implementor that sees most of these routines, and they can
+>> be hidden in the private part of the pool implementors package.
+> Not really, in that U_D_S is not overridable, so the users will have
+> to know about the inherited routines in order to use it (it won't be
+> in the source!). And once they have to do that, whether the
+> implementation "is hidden in the private part" is irrelevant - they'll
+> see the entire set of routines that they don't need to use.
+
+Having just a rename of U_D_S in the source to whereever it lives seems like a
+reasonable approach to me. That way, the user sees all the needed calls in the
+one source.
+
+>> When the pool is finalized, I wanted a protected operation that frees
+>> all the subpools.
+>>
+>> The initial approach I took was to call U_D_S for each of these.
+>> However, that leaves the P.O.
+>> and then dispatches back to a routine that likely needs to modify the
+>> pool object's subpool list.
+>> It can't however because the P.O. is already locked out, which leads
+>> to a deadlock.
+>> This is probably a good reason why U_D_S should be a potentially
+>> blocking operation.
+
+> Pool writers never, ever call U_D_S. That's one reason why it wasn't
+> in the pool package. :-)
+
+Thats not true, I *have* to call U_D_S from my U_D_O call.
+
+****************************************************************
+
+From: Brad Moore
+Sent: Saturday, April 16, 2011 8:03 PM
+
+One more question:
+
+The function Default_Subpool_for_Pool raises Program_Error if the root subpools
+version is called. Would it make more sense to raise Constraint_Error or
+Storage_Error instead, or perhaps return a null subpool handle instead? Is it
+really a program error to make a dispatching call to a pool that doesn't
+override that function? It doesn't seem like the pool writer has an error in his
+program, and given that some pools are expected to return something, it doesn't
+seem like it is a program error for the caller if the caller happens to get
+passed a pool that doesn't do an override of this function.
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Saturday, April 16, 2011 11:02 PM
+
+If the pool writer doesn't override this function, an "normal" allocator ("new
+T") cannot work (it is defined to call Default_Subpool_for_Pool to get the
+subpool), so an exception is required (returning null won't work). Which
+exception isn't a big deal. I don't like raising Storage_Error in this case,
+because the problem is not insufficient storage, but rather a pool that doesn't
+support a default -- and I'd rather that distinction is visible to the caller.
+So that leaves Constraint_Error or Program_Error. To me, this seems more like a
+bug than something that pool writers ought to be doing, (which suggests
+Program_Error) but perhaps YMMV.
+
+****************************************************************
+
+From: Bob Duff
+Sent: Thursday, April 21, 2011 10:55 PM
+
+Here's a new version of AI05-0111-3, Subpools, allocators, and control of
+finalization. [This is version /09 of the AI - Editor.]
+
+I addressed all the emails I've seen so far, even though I didn't respond
+directly to every email.
+
+The one thing I might not have addressed properly is who (if anybody) is
+responsible for null-ing out subpool handles. I left the AI as is in this
+regard. I'm not at all sure that's right, which may be a reason to give up on
+this AI for Ada 2012.
+
+****************************************************************
+
+From: Bob Duff
+Sent: Thursday, April 21, 2011 10:57 PM
+
+> > procedure Deallocate_Subpool(
+> > Pool : in out Root_Storage_Pool_with_Subpools;
+> > Subpool : in out Subpool_Handle) is abstract
+> > with Pre'Class => Pool_of_Subpool(Subpool) = Pool'Access;
+> > -- Deallocate the space for all of the objects allocated from the
+> > -- specified subpool. Unchecked_Deallocate_Subpool calls this.
+
+> By "Deallocate the space", is it acceptable to not actually deallocate
+> space, but make the space available for reuse?
+
+"Deallocate space" and "make space available for reuse" seem synonymous, to me.
+Anyway, Deallocate_Subpool does whatever it does -- here, we're really just
+hinting at the intent. It's entirely up to the programmer whether it's available
+for reuse by allocators for the same [sub]pool, or other pools, or other
+processes.
+
+But I can imagine somebody making it do nothing, and somebody else making it
+raise an exception.
+
+> In my new Deepend version, this function is invoked by two separate
+> calls. I have a primitive Unchecked_Deallocate_Subpool, which sets a
+> flag in the subpool to indicate full deallocation of the subpool, then
+> it calls Ada.Unchecked_Deallocate_Subpool, which then calls
+> Deallocate_Subpool, and deallocates all the storage.
+> This is a convenience primitive so that clients dont have to with
+> Ada.Unchecked_Deallocation, and can do everything using the primitives
+> of the subpool.
+>
+> I also have a Unchecked_Deallocate_Objects, which sets a flag in the
+> subpool to indicate only make the allocated space available for reuse,
+> then calls Ada.Unchecked_Deallocate_Subpool, which then calls
+> Deallocate_Subpool, which then makes the space reusable, then clears
+> the flag in the subpool, so that a subsequent call to
+> Ada.Unchecked_Deallocate_Subpool will work as expected.
+>
+> This raises another question. Why can't Unchecked_Deallocate_Subpool
+> be a primitive of Root_Storage_Pool_With_Subpools?
+
+It seems convenient to keep it separate, because lots of clients will be doing
+"new" and "Unchecked_Deallocate_Subpool", and don't need to mess around with the
+Subpools package itself.
+
+Also, it's analogous to Ada.Unchecked_Deallocation, so it's under Ada and has a
+similar name.
+
+> My understanding is that this was made a separate library unit because
+> people were worried that someone might override the primitive and not
+> call the ancestor version of the primitive.
+
+Could be -- I don't remember that.
+
+>...Now that
+> we have these new fandangled postconditions, I think this could be
+>reasonably enforced by by having a postcondition on the call.
+>
+> If we had the function;
+>
+> function Objects_Need_Finalization
+> (Subpool : Subpool_Handle) return Boolean;
+> -- Returns true if there are objects allocated from the pool that have
+> -- not been deallocated and need finalization.
+>
+> then we could have the primitive;
+>
+> procedure Unchecked_Deallocate_Subpool
+> (Subpool : in out Subpool_Handle)
+> with Post'Class => (not Objects_Need_Finalization (Subpool));
+>
+> And regardless whether it is deemed a good idea to make
+> Unchecked_Deallocate_Subpool a primitive, Could we add the
+> Objects_Need_Finalization call? I would use that in postconditions in
+> my Deepend pool, if it was available. It would make available another
+> useful bit of information about the implementions finalization that I
+> think should be easy to implement.
+
+Well, I'm inclined to say, "Good idea for Ada 2020".
+
+We can't keep fiddling with this AI forever. If there are bugs, we should fix
+them, but the stuff you're talking about here seems more like "bells" or
+"whistles".
+
+> > A call to Subpools.Allocate(P, Addr, Size, Align) does the following:
+> >
+> > Allocate_From_Subpool
+> > (Root_Storage_Pool_with_Subpools'Class(P),
+> > Addr, Size, Align,
+> > Subpool => Default_Subpool_for_Pool
+> > (Root_Storage_Pool_with_Subpools'Class(P)));
+> >
+>
+> I thought this wasn't true anymore now that we are supporting the two
+> implementation models.
+
+This is necessary for the two implemention models to have the same semantics.
+
+****************************************************************
+
+From: Brad Moore
+Sent: Thursday, April 21, 2011 11:38 PM
+
+> Here's a new version of AI05-0111-3, Subpools, allocators, and control
+> of finalization.
+
+I had a quick scan through. Looks good to me.
+
+> The one thing I might not have addressed properly is who (if anybody)
+> is responsible for null-ing out subpool handles. I left the AI as is
+> in this regard. I'm not at all sure that's right, which may be a
+> reason to give up on this AI for Ada 2012.
+
+I think having Ada.U_D_S null the handle, as you have it in the AI makes sense
+to me.
+
+****************************************************************
+
+From: Brad Moore
+Sent: Friday, April 22, 2011 12:15 AM
+
+> Well, I'm inclined to say, "Good idea for Ada 2020".
+> We can't keep fiddling with this AI forever. If there are bugs, we
+> should fix them, but the stuff you're talking about here seems more
+> like "bells" or "whistles".
+
+Another Idea to maybe file away for Ada 2020 would be have have another pool
+type derived from System.Storage_Pools.Root_Storage_Pool that provides the hook
+to allow controlled types to be finalized, but without subpools.
+
+Such a pool couldn't use the new allocator syntax involving subpool handles.
+However, if you declare such pool objects in nested scopes, and declare access
+types to the objects you want to allocate in these nested scopes, then you
+really don't need subpools.
+
+I found a slight performance benefit using this pool model, over the subpool
+approach, when using the existing Ada "new" allocator. I think the performance
+differences result from not having to call Default_Subpool_For_Pool, and the
+state data that would have otherwise been stored in the subpool object can be
+stored directly in the pool object. Also, in my model where only one task can
+allocate from such a pool instance, this model is quite a bit simpler than the
+subpool model, because there is no need for a protected object in the pool to
+manage the list of subpools.
+
+I still can think of cases where you would want subpools, so I think we need the
+AI as currently proposed. I can foresee a need for an even simpler, slightly
+more efficient abstraction however, that provides a subset of the subpool
+functionality for those that always want to use allocators without subpools.
+
+This can be added later, post Ada 2012, if the idea has merit.
+
+****************************************************************
+
+From: Bob Duff
+Sent: Monday, April 25, 2011 6:28 PM
+
+A couple weeks ago, there was some discussion about how terminate alternatives
+should work for tasks allocated within subpools. I said something like, "I don't
+care how, or even if, they work!" Because terminate alternatives are primarily
+useful for library-level tasks that live forever anyway; that it's, they're for
+shutting down entire programs.
+
+Well, I got curious, and did some experimentation.
+I ran part of AdaCore's regression test suite with a compiler instrumented to
+detect terminate alternatives.
+
+133 out of 12951 tests have one or more terminate alts.
+220 terminate alternatives in these tests.
+133 / 12951 = 0.010 .
+Somewhat rare, but I actually would have guessed it's rarer than that. Maybe
+it's biased by the fact that terminate alts were (over the years) buggier than,
+say, the built-in "not" operator. ;-)
+
+Almost all of those are for library level tasks, or are within a library level
+procedure. Library level procedures don't count, because they're presumably
+test programs, not real code. (I spot checked, and that seems to be the case.)
+
+There are 2 exceptions. That is, 2 cases where real code has a terminate
+alternative, in a procedure or task, in a library package.
+
+This is all superseded by the idea of disallowing tasks entirely (or dropping
+the AI entirely), but I thought I'd report the results anyway, because it's
+interesting.
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Monday, April 25, 2011 10:04 PM
+
+> 133 out of 12951 tests have one or more terminate alts.
+> 220 terminate alternatives in these tests.
+> 133 / 12951 = 0.010 .
+> Somewhat rare, but I actually would have guessed it's rarer than that.
+> Maybe it's biased by the fact that terminate alts were (over the
+> years) buggier than, say, the built-in "not"
+> operator. ;-)
+
+A more interesting question is the ratio versus task bodies (since these can
+only appear in a task body). I would guess that large numbers of your tests
+don't include tasks (that's surely true with the stuff in our test suite) and
+thus make the numbers look far smaller than realistic.
+
+> Almost all of those are for library level tasks, or are within a
+> library level procedure. Library level procedures don't count,
+> because they're presumably test programs, not real code.
+> (I spot checked, and that seems to be the case.)
+>
+> There are 2 exceptions. That is, 2 cases where real code has a
+> terminate alternative, in a procedure or task, in a library package.
+
+OK, but again, it is important to know how many library level tasks are
+involved. Perhaps there are only three tests with library level tasks? There is
+no context to this number. Tests without tasks are irrelevant in determining how
+tasks should behave.
+
+Moreover, there is another piece of missing information: how are the associated
+task objects created? Single tasks, array of tasks, allocated tasks, records
+containing tasks then used in some data structure, etc. Whether or not it
+matters seems to require that.
+
+> This is all superseded by the idea of disallowing tasks entirely (or
+> dropping the AI entirely), but I thought I'd report the results
+> anyway, because it's interesting.
+
+I think it is misleading at best. Many of my tasks have terminate alternatives,
+because the alternate ways to terminate are clunky (explicit shutdown entries)
+or dangerous (abort) or hard to arrange (only one time use of the task).
+
+(Note that I agree it is irrelevant for Ada 2012, but I disagree with your
+premise.)
+
+I ran a search in four real systems that I've been involved in writing. Claw
+(everyone knows about this); Indexer (the crawler for the Ada IC search engine
+and related tools); Web Server (the web server used to run Ada-Auth.Org and
+other sites); and Trash-Finder (the spam filter and mail gateway). (None of the
+other serious programs that I've been involved in have used any tasks.) All of
+these involve Ada code in programs that have been executing within the last week
+(most are running 24/7). The numbers might be skewed somewhat as must of these
+use some variation on the worker task pattern; it's nothing but a data point:
+
+Claw (6,686K of source in 182 files): 2 terminate alternatives; 2 task bodies =
+100% of task bodies contain a terminate alternative. Trash-Finder Gateway (324K
+of source in 19 files): no terminate alternatives; 13 task bodies = 0% of task
+bodies contain a terminate alternative. (This program uses explicit shutdown
+entries; that would make it a poor candidate to use storage pools in any case.)
+Trash-Finder Viewer (886K of source in 56 files): 3 terminate alternatives; 4
+task bodies = 75% of task bodies contain a terminate alternative. Indexer (500K
+of source in 54 files): 2 terminate alternatives; 3 task bodies = 66% of task
+bodies contain a terminate alternative. Web Server (600K of source in 24 files):
+no terminate alternatives; 2 task bodies = 0% of task bodies contain a terminate
+alternative. (Again, this uses explicit shutdown entries.)
+
+[Methodology: I searched for "terminate" and "task body" in the source code for
+each of these programs, and counted the number of hits outside of comments. I
+only searched the primary source directories, so these figures don't include any
+shared code -- necessary to avoid double counting -- but I don't think there are
+many tasks in that code anyway.]
+
+Totals: 7 terminate alternatives; 24 task bodies = 29% of task bodies contain a
+terminate alternative. (9MB of source in 335 files; that represents at least 170
+units [some files have more than one unit].)
+
+Moral: You can make statistics prove anything you want. :-)
+
+Second moral: It's hard to write tasks that terminate without a terminate
+alternative or shutdown entry; and shutdown entries don't work in a subpool
+context (you'd have to iterate all of the objects to call that entry, which
+would completely defeat the purpose of doing an en-masse deallocation). Not a
+single "real" task that I've been involved with used any other technique for
+termination.
+
+****************************************************************
+
+From: Robert Dewar
+Sent: Monday, April 25, 2011 11:28 PM
+
+> Moral: You can make statistics prove anything you want. :-)
+
+Well I must say I don't put much credence in four programs by one author compared to a collection of well over 10 million lines of code from hundreds of different sources.
+>
+> Second moral: It's hard to write tasks that terminate without a
+> terminate alternative or shutdown entry; and shutdown entries don't
+> work in a subpool context (you'd have to iterate all of the objects to
+> call that entry, which would completely defeat the purpose of doing an
+> en-masse deallocation). Not a single "real" task that I've been
+> involved with used any other technique for termination.
+
+But those are indeed "tasks *you* have been involved with"
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Tuesday, April 26, 2011 2:18 AM
+
+> > Moral: You can make statistics prove anything you want. :-)
+>
+> Well I must say I don't put much credence in four programs by one
+> author compared to a collection of well over 10 million lines of code
+> from hundreds of different sources.
+
+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.
+
+> > Second moral: It's hard to write tasks that terminate without a
+> > terminate alternative or shutdown entry; and shutdown entries don't
+> > work in a subpool context (you'd have to iterate all of the objects
+> > to call that entry, which would completely defeat the purpose of
+> > doing an en-masse deallocation). Not a single "real" task that I've
+> > been involved with used any other technique for termination.
+>
+> But those are indeed "tasks *you* have been involved with"
+
+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? Or do they not terminate at all (which makes sense in
+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.
+
+****************************************************************
Questions? Ask the ACAA Technical Agent