Version 1.1 of ai12s/ai12-0302-1.txt

Unformatted version of ai12s/ai12-0302-1.txt version 1.1
Other versions for file ai12s/ai12-0302-1.txt

!standard A etc.          19-01-10 AI12-0302-1/01
!class Amendment 19-01-10
!status work item 19-01-10
!status received 19-01-10
!priority High
!difficulty Medium
!subject Default Global aspect for language-defined units
Language-defined units declared as Pure will be implicitly Global => null. Other packages (generic or not) will have Global => synchronized in out <unit>.
In the absence of a Global aspect, the default is "Global => in out all" unless a (generic) package is declared Pure. This is not consistent with the requirement of RM A(3/5) that language-defined (generic) packages be reentrant.
For language-defined units declared Pure, we will have the implicit Global => null. For others, we will insert an explicit:
Global => synchronized in out <unit_name>
where <unit_name> is the name of the package or generic package for which the Global aspect is specified. For library (generic) subprograms that are not merely renames of some subprogram declared elsewhere, the <unit_name> will refer to the parent package (or generic package) of the library (generic) subprogram.
Below are two lists of the language-defined units. The first list is those declared Pure. The second list is of those not declared Pure. We have reviewed the second list and made certain that "Global => synchronized in out <unit_name>" is appropriate for each. Some will have individual operations that can be specified as Global => null, if their result is purely a function of their inputs. And some, in particular in the I/O packages, will need to indicate their use of an unknown, unsynchronized global corresponding to Current_Input or Current_Output, as explained in RM A(3.1/4). For these, ideally we could write either:
Global => (in out Current_Input.all, synchronized in out Text_IO)
Global => (in out Current_Output.all, synchronized in out Text_IO)
but alas, Current_Input and Current_Output return a File_Type, which is limited private, rather than a visible access type. So we are relegated to simply:
Global => in out Text_IO
presuming that the associated state is all kept in a collection that is part of Text_IO, but is not synchronized. This would mean that two concurrent subprogram calls using either Current_Input or Current_Output would be considered to conflict.
A more general problem has to do with parameters that are clearly "handles" or equivalent, such as a File_Type, random number Generator, or a task object. Even though they are passed as IN parameters, the subprogram can clearly update their associated state. One choice is to consider all of this state as residing in the associated package, as we did above for Current_Input and Current_Output. Alternatively, we could generalize the Global aspect to allow us to specify the name of an IN parameter with mode "in out" to indicate that the state "owned" by the IN parameter is in fact updated by the call. Hence:
function Random(Gen : Generator) return Result_Subtype with Global => in out Gen;
However that is a bit of a perversion of the notion of a Global aspect, and provides additional justification for introducing a separate aspect for identifying things that are modified by a call, that might not necessarily be considered "global." Hence, we could introduce a new "Modifies" aspect which is specifically designed to allow one to specify more precisely what is possibly modified by a call, including a particular part of a visibly composite parameter. Hence:
function Random(Gen : Generator) return Result_Subtype with Modifies => Gen;
This would be used to more precisely indicate what is being modified, and also allow the ability to say that state associated with an IN parameter is modified. We will have to decide whether it is worth defining this additional Modifies aspect for this purpose. The alternative, as mentioned, is to presume the state is part of some collection within the enclosing (generic) package (e.g. Discrete_Random) and fall back on:
function Random(Gen : Generator) return Result_Subtype with Global => in out Discrete_Random;
This overstates the effects of Random, effectively considering concurrent uses of otherwise independent random number streams as being conflicting.
Note that if we accept the notion that we treat a handle as "owning" any data "associated" with the handle, we could identify Current_Input or Current_Output in the Global aspect for a subprogram like Put_Line:
procedure Put_Line (Item : String) with Global => (in out Current_Output, synchronized in out Text_IO);
Here "Global" does seem appropriate, since there is no parameter that is specifying the file being modified. It is a bit odd that you must call a function (Current_Output in this case) to determine what global object is being updated, but this makes sense in the context of a handle that is considered to "own" the associated updatable state.
Finally, we have functions that return generalized references into another object, e.g.:
function Reference(Container : aliased in out Map; ...) return Reference_Type;
How do we specify that the retured reference refers to some part of Container. This is probably best handled with a postcondition using the Overlaps_Storage attribute:
function Reference(Container : aliased in out Map; ...) return Reference_Type; with Post => Container'Overlaps_Storage(Reference'Result.Element.all);
presuming X'Overlaps_Storage(Y) in the presence of owner pointers means Y overlaps with something "owned" (directly or indirectly) by X.
So to summarize the proposal, each library unit will have a default specification of the Global aspect, to either "null" for pure library units, or "synchronized in out <unit_name>" for impure library units. And then within the impure units, individual subprograms will override this default when they refer to implicit state (Current_Input or Current_Output) or they have "in" parameters that are handles owning updatable state that is not required by the language to be synchronized.
The relevant subprograms requiring special Global aspects (and/or Modifies aspects, should we decide to have such an aspect):
* Put/Get/Set operations on Current_Output/Current_Input/Current_Error
* Put/Get/.. operations on File_Type parameters where the File_Type is an IN parameter.
* Operations on Random Number generators where the generator is an IN parameter
--------------- The Pure group: ---------------
Standard A.1
Ada A.2
Assertions 11.4.2 Characters A.3.1
Conversions A.3.4 Handling A.3.2 Latin_1 A.3.3
Containers A.18.1
Bounded_Doubly_Linked_Lists A.18.20 Bounded_Hashed_Maps A.18.21 Bounded_Hashed_Sets A.18.23 Bounded_Multiway_Trees A.18.25 Bounded_Ordered_Maps A.18.22 Bounded_Ordered_Sets A.18.24 Bounded_Vectors A.18.19 Generic_Array_Sort A.18.26 Generic_Constrained_Array_Sort A.18.26 Generic_Sort A.18.26
Decimal F.2 IO_Exceptions A.13 Iterator_Interfaces 5.5.1 Locales A.19 Numerics A.5
Complex_Arrays G.3.2 Complex_Elementary_Functions G.1.2 Complex_Types G.1.1 Elementary_Functions A.5.1 Generic_Complex_Arrays G.3.2 Generic_Complex_Elementary_Functions G.1.2 Generic_Complex_Types G.1.1 Generic_Elementary_Functions A.5.1 Generic_Real_Arrays G.3.1 Real_Arrays G.3.1
Streams 13.13.1 Strings A.4.1
Equal_Case_Insensitive A.4.10 Hash A.4.9 Hash_Case_Insensitive A.4.9 Less_Case_Insensitive A.4.10 Maps A.4.2 Constants A.4.6 UTF_Encoding A.4.11 Conversions A.4.11 Strings A.4.11 Wide_Strings A.4.11 Wide_Wide_Strings A.4.11 Wide_Equal_Case_Insensitive A.4.7 Wide_Hash A.4.7 Wide_Hash_Case_Insensitive A.4.7 Wide_Wide_Equal_Case_Insensitive A.4.8 Wide_Wide_Hash A.4.8 Wide_Wide_Hash_Case_Insensitive A.4.8
Unchecked_Conversion 13.9 Unchecked_Deallocate_Subpool 13.11.5 Unchecked_Deallocation 13.11.2 Wide_Characters A.3.1
Handling A.3.5
Wide_Wide_Characters A.3.1
Handling A.3.6
Interfaces B.2
C B.3 COBOL B.4 Fortran B.5
System 13.7
Storage_Elements 13.7.1
----------------- The impure group: -----------------
Asynchronous_Task_Control D.11 Calendar 9.6
Arithmetic 9.6.1 Formatting 9.6.1 Time_Zones 9.6.1
Command_Line A.15 Complex_Text_IO G.1.3 [Containers]
Bounded_Priority_Queues A.18.31 Bounded_Synchronized_Queues A.18.29 Doubly_Linked_Lists A.18.3 Hashed_Maps A.18.5 Hashed_Sets A.18.8 Indefinite_Doubly_Linked_Lists A.18.12 Indefinite_Hashed_Maps A.18.13 Indefinite_Hashed_Sets A.18.15 Indefinite_Holders A.18.18 Indefinite_Multiway_Trees A.18.17 Indefinite_Ordered_Maps A.18.14 Indefinite_Ordered_Sets A.18.16 Indefinite_Vectors A.18.11Standard (...continued) Multiway_Trees A.18.10 Ordered_Maps A.18.6 Ordered_Sets A.18.9 Unbounded_Priority_Queues A.18.30 Unbounded_Synchronized_Queues A.18.28 Vectors A.18.2
Direct_IO A.8.4 Directories A.16
Hierarchical_File_Names A.16.1 Information A.16
Dispatching D.2.1
EDF D.2.6 Non_Preemptive D.2.4 Round_Robin D.2.5
Dynamic_Priorities D.5.1 Environment_Variables A.17 Exceptions 11.4.1 Execution_Time D.14
Group_Budgets D.14.2 Interrupts D.14.3 Timers D.14.1
Finalization 7.6 Float_Text_IO A.10.9 Float_Wide_Text_IO A.11 Float_Wide_Wide_Text_IO A.11 Integer_Text_IO A.10.8 Integer_Wide_Text_IO A.11 Integer_Wide_Wide_Text_IO A.11 Interrupts C.3.2
Names C.3.2
Discrete_Random A.5.2 Float_Random A.5.2
Real_Time D.8
Timing_Events D.15
Sequential_IO A.8.1 Storage_IO A.9 [Streams]
Stream_IO A.12.1
Bounded A.4.4 Equal_Case_Insensitive A.4.10 Hash A.4.9 Hash_Case_Insensitive A.4.9 Less_Case_Insensitive A.4.10 Fixed A.4.3 Equal_Case_Insensitive A.4.10 Hash A.4.9 Hash_Case_Insensitive A.4.9 Less_Case_Insensitive A.4.10 Unbounded A.4.5 Equal_Case_Insensitive A.4.10 Hash A.4.9 Hash_Case_Insensitive A.4.9 Less_Case_Insensitive A.4.10 Wide_Bounded A.4.7 Wide_Equal_Case_Insensitive A.4.7 Wide_Hash A.4.7 Wide_Hash_Case_Insensitive A.4.7 Wide_Fixed A.4.7 Wide_Equal_Case_Insensitive A.4.7 Wide_Hash A.4.7 Wide_Hash_Case_Insensitive A.4.7 Wide_Maps A.4.7 Wide_Constants A.4.7 Wide_Unbounded A.4.7 Wide_Equal_Case_Insensitive A.4.7 Wide_Hash A.4.7 Wide_Hash_Case_Insensitive A.4.7 Wide_Wide_Bounded A.4.8 Wide_Wide_Equal_Case_Insensitive A.4.8 Wide_Wide_Hash A.4.8 Wide_Wide_Hash_Case_Insensitive A.4.8 Wide_Wide_Fixed A.4.8 Wide_Wide_Equal_Case_Insensitive A.4.8 Wide_Wide_Hash A.4.8 Wide_Wide_Hash_Case_Insensitive A.4.8 Wide_Wide_Maps A.4.8 Wide_Wide_Constants A.4.8 Wide_Wide_Unbounded A.4.8 Wide_Wide_Equal_Case_Insensitive A.4.8 Wide_Wide_Hash A.4.8 Wide_Wide_Hash_Case_Insensitive A.4.8
Synchronous_Barriers D.10.1 Synchronous_Task_Control D.10
EDF D.10
Tags 3.9
Generic_Dispatching_Constructor 3.9
Task_Attributes C.7.2 Task_Identification C.7.1 Task_Termination C.7.3 Text_IO A.10.1
Bounded_IO A.10.11 Complex_IO G.1.3 Editing F.3.3 Text_Streams A.12.2 Unbounded_IO A.10.12
Unchecked_Deallocate_Subpool 13.11.5 Unchecked_Deallocation 13.11.2 Wide_Text_IO A.11
Complex_IO G.1.4 Editing F.3.4 Text_Streams A.12.3 Wide_Bounded_IO A.11 Wide_Unbounded_IO A.11
Wide_Wide_Text_IO A.11
Complex_IO G.1.5 Editing F.3.5 Text_Streams A.12.4 Wide_Wide_Bounded_IO A.11 Wide_Wide_Unbounded_IO A.11
[C] Pointers B.3.2 Strings B.3.1
Address_To_Access_Conversions 13.7.2 Machine_Code 13.8 Multiprocessors D.16 Dispatching_Domains D.16.1 RPC E.5 Storage_Pools 13.11 Subpools 13.11.4
The rules given in RM A(3/5-3.1/4) ensure that any globals referenced by language-defined packages are synchronized, except in the special case of the files identified by Current_Input and Current_Output. For these, as proposed above, we will specify the side effects using an appropriate Global aspect. Also, for cases where a parameter mode of IN is used for an operand that clearly is associated with updatable state, a Global aspect or a Modifies aspect (should we decide to support that) will be used to capture the fact that some potentially non-synchronized state is being updated.
No ASIS effect.
Unclear whether detailed testing is worthwhile, but some C-Tests that show that language-defined packages work in parallel operations when the default conflict checking policy is in effect would be valuable.

From: Tucker Taft
Sent: Tuesday, January 08, 2019 10:16 PM

Here is a first attempt to indicate how we will specify the Global aspect of 
language-defined units. [This is version /01 of the AI - Editor.]

No wording yet.


Questions? Ask the ACAA Technical Agent