AI22-0052-1

!standard 13.11(17.1/5)                               23-03-17  AI22-0052-1/03

!standard 13.11(18/5)

!standard H.7(4/5)

!standard H.7(7/5)

!class Binding Interpretation 22-10-27

!status work item 22-10-27

!status received 22-10-27

!priority Low

!difficulty Easy

!qualifier Omission

!subject Storage Pool-related side effects

!summary

The Storage_Pool attribute of an access type may be used as a global name in order to more conveniently describe the effects of the implicit Storage_Pool calls associated with constructs such as allocators and unchecked deallocations.

Standard storage pools are considered synchronized for the purposes of Global aspects.

!issue

Global aspects for an entity include the effect of all calls inside of that entity, including any implicit calls. This means that the implicit calls on the storage pool of an access type are included for any allocation or deallocation operations.

However, for a generic formal access-to-object type, there is no current way to describe this storage pool. The storage pool is that of the actual type, and the properties of that pool are not known in the generic template. This leaves in out all as the only global specification that can be applied to a generic operation that does any allocations or deallocations of a formal access type. A way to name the storage pool of an access type in a global specification would eliminate this problem.

!recommendation

To help in describing the effects of the (implicit) storage pool calls associated with an allocator or an unchecked deallocation, a Storage_Pool attribute reference may be used as a global name. This includes the case where the attribute prefix denotes a formal access-to-subprogram type. This is an Annex H feature.

Additionally, standard storage pool(s) can be assumed to be synchronized objects. They are required to allow concurrent operation, and this should be reflected in the coverage of global specifications.

!wording

Modify 13.11(17.1/5):

The type(s) of the standard pool(s), and the primitive Allocate, Deallocate, and Storage_Size subprograms for the standard pool(s) are nonblocking. Concurrent invocations of these subprograms do not conflict with one another (see 9.10) when applied to standard storage pools. {Standard storage pool objects are considered to be synchronized objects.}

{AARM Discussion: This does not imply that a standard storage pool has to be a protected object, only that concurrent calls are supported.}

{AARM Ramification: This implies that the global specification in out synchronized is sufficient to cover the implicit call on Allocate generated by an allocator for a standard storage pool. Alternatively, a standard storage pool can be included in a global specification using the attribute Storage_Pool of an appropriate access type (see H.7).}

Modify 13.11(18/5):

If Storage_Size is specified for an access type T, an implementation-defined pool P is used for the type. The Storage_Size of P is at least that requested, and the storage for P is reclaimed when the master containing the declaration of the access type is left. If the implementation cannot satisfy the request, Storage_Error is raised at the freezing point of type T. The storage pool P is used only for allocators returning type T or other access types specified to use T'Storage_Pool. Storage_Error is raised by an allocator returning such a type if the storage space of P is exhausted (additional memory is not allocated). The type of P, and the primitive Allocate, Deallocate, and Storage_Size subprograms of P are nonblocking.{ Concurrent invocations of these subprograms do not conflict with one another (see 9.10) when applied to P, and P is considered a synchronized object.}

[Editor’s note: The concurrent invocation wording is missing from this implementation-defined pool; note that this is not a standard storage pool, but we want similar rules to apply to it as do standard storage pools.]

Add after H.7(4/5):

An object_name used as a global_name may also be an attribute_reference with attribute designator Storage_Pool. [Redundant: The attribute prefix may denote a formal access-to-object type.]

 Modify H.7(7/5):

The Global aspect for a subtype identifies the global variables that might be referenced during default initialization, adjustment as part of assignment, finalization of an object of the subtype, or conversion to the subtype, including the evaluation of any assertion expressions that apply. {For a formal access-to-object subtype, or an access-to-object subtype whose storage pool is not a standard storage pool, the Global aspect identifies the global variables (other than the storage pool itself) that might be referenced by a call on Allocate, Deallocate, or Storage_Size for the storage pool type.} ... [Note: the rest is unchanged]

!discussion

As explained in the !issue, side effects on storage pools can be significant. This AI attempts to address this. We only enforce checks on storage pools if the restriction No_Hidden_Indirect_Globals is present, since without that restriction the use of access types is not necessarily reflected at all within global aspects.

For standard storage pools, we define them to be synchronized objects. In particular, allocation needs to be included. We worry about allocation because if we were to write "Global => null" for a function that returns the result of an allocator, that implies that the function returns the same result on each invocation, which is clearly not the case. But this global specification would be illegal, since the implicit call on Allocate needs to be covered by the global specification, and the standard storage pool object is a global synchronized object. It either has to be named with a Storage_Pool attribute, or a more general specification like in out synchronized needs to be used.  

Note that AI22-0059-1 addresses a related issue, more formally defining the meaning of “Concurrent invocations of these subprograms do not conflict with one another (see 9.10)” in the 13.11 wording above. Adoption of AI22-0059-1 does not eliminate the need to explicitly state that implementation-created storage pools can be treated as synchronized.

!example

        type A is access Integer;
       type B is access Integer;
       for B'Storage_Pool use My_Cool_Storage_Pool;
   
       function New_A (X : Integer) return A
          with Global => in out synchronized;
         
       function New_B (Y : Integer) return B
          with Global => in out all;
            -- "in out synchronized" would not cover B'Storage_Pool
            -- unless My_Coll_Storage_Pool is a synchronized object
         
       function Another_New_B (Z : Integer) return B
          with Global => in out B'Storage_Pool;

!ACATS test

ACATS B and C-Tests are needed to check that Storage_Pools are included in the global as needed (or the code is rejected if not), when No_Hidden_Indirect_Globals is in effect..

!appendix

This AI was originally considered as AI12-0410-1, which was deferred. This AI initially contained all of the relevant contents of that AI. There was no e-mail filed in that AI.

**********************************************************************