CVS difference for ai12s/ai12-0119-1.txt

Differences between 1.12 and version 1.13
Log of other versions for file ai12s/ai12-0119-1.txt

--- ai12s/ai12-0119-1.txt	2018/01/11 02:26:11	1.12
+++ ai12s/ai12-0119-1.txt	2018/01/11 04:50:10	1.13
@@ -1,4 +1,4 @@
-!standard 5.5.2 (2/3)                              18-01-01    AI12-0119-1/06
+!standard 5.5.2(2/3)                               18-01-10    AI12-0119-1/07
 !class Amendment 14-06-20
 !status work item 14-06-20
 !status received 14-06-17
@@ -46,7 +46,7 @@
 - To support the development of complete programs that maximize
   parallelism;
 - To efficiently guide the compiler in the creation of effective
-  parallelism (without oversubscription of the parallelism resources) with 
+  parallelism (without oversubscription of the parallelism resources) with
   minimal input from the programmer;
 - To avoid syntax that would make a POP erroneous or produce noticeably
   different results if executed sequentially vs in parallel.
@@ -58,10 +58,10 @@
 
 Note that in this model the compiler will identify any code where a
 potential data race occurs (following the rules for concurrent access
-to objects as specified in the Language Reference Manual RM 9.10(11),
-and point out where objects cannot be guaranteed to be independently
-addressable. If not determinable at compile-time, the compiler may
-insert run-time checks to detect data overlap.
+to objects as specified in the 9.10(11-14), and point out where objects
+cannot be guaranteed to be independently addressable. If not determinable
+at compile-time, the compiler may insert run-time checks to detect data
+overlap.
 
 This model also disallows potentially blocking operations within parallel
 block statements and parallel loop statements, to simplify the implementation
@@ -79,12 +79,12 @@
 operations. Note that this is consistent with the current standard which
 already supports multiple concurrent calls by a single task in the
 presence of the asynchronous transfer of control capability
-(RM 9.7.4 (23)).
+(9.7.4 (23)).
 
 There are two areas of this proposal; one that introduce capabilities
 for parallel/concurrent blocks, and another that introduces capabilities for
 parallel loops. A third proposal that introduces capabilities for parallel
-reduction is covered in a separate AI, AI-????????.
+reduction is covered in a separate AI, AI12-0242-1.
 
 Parallel Blocks
 ---------------
@@ -94,37 +94,37 @@
 
 Semantics: A parallel block statement encloses two or more sequences of
 statements (two or more "parallel sequences") separated by the reserved
-word "and".  Each parallel sequence represents a separate tasklet, but
+word "and". Each parallel sequence represents a separate tasklet, but
 all within a single Ada task. Task identity remains that of the
 enclosing Ada task, and a single set of task attributes is shared
 between the tasklets. Each sequence of statements is assigned a unique
 and independent executor to execute the tasklet.
 
-With respect to the rules for shared variables (see RM 9.10(13)), two
-actions occurring within two different parallel sequences of the same
-parallel block are not automatically sequential, so execution can be
-erroneous if one such action assigns to an object, and the other reads
-or updates the same object or a neighboring object that is not
-independently addressable from the first object.  Potentially blocking
-operations are not allowed in a parallel sequence of a parallel block.  
-Otherwise, the appropriate use of atomic, protected, or task objects (which as 
+With respect to the rules for shared variables (see 9.10(11-14), and
+specifically 9.10(13)), two actions occurring within two different parallel
+sequences of the same parallel block are not automatically sequential, so
+execution can be erroneous if one such action assigns to an object, and the
+other reads or updates the same object or a neighboring object that is not
+independently addressable from the first object. Potentially blocking
+operations are not allowed in a parallel sequence of a parallel block.
+Otherwise, the appropriate use of atomic, protected, or task objects (which as
 a group we will call synchronized objects) can be used to avoid erroneous execution.
 
-In addition, the new Global and Nonblocking aspects may be specified to enable 
-the static detection of such problems at compile time (see AI12-0079-1 and 
-AI12-0064-1).
+In addition, the new Global and Nonblocking aspects may be specified to enable
+the static detection of such problems at compile time (see AI12-0079-1 and
+AI12-0064-2).
 
 Any transfer of control out of one parallel sequence will initiate the
-aborting of the other parallel sequences not yet completed.  Once all
+aborting of the other parallel sequences not yet completed. Once all
 other parallel sequences complete normally or abort, the transfer of
-control takes place.  If multiple parallel sequences attempt a transfer
-of control before completing, the first occurrence of transfer of control is 
+control takes place. If multiple parallel sequences attempt a transfer
+of control before completing, the first occurrence of transfer of control is
 selected and the others are aborted.
 
 If an exception is raised by any of the parallel sequences, it is
-treated similarly to other forms of transfer of control, with the exception being
-propagated only after all the other sequences complete normally or due
-to abortion.  If multiple parallel sequences executing in parallel
+treated similarly to other forms of transfer of control, with the exception
+being propagated only after all the other sequences complete normally or due
+to abortion. If multiple parallel sequences executing in parallel
 raise an exception before completing, the first occurrence is chosen and the
 others are aborted. The parallel block completes when all of the
 parallel sequences complete, either normally or by being aborted.
@@ -161,55 +161,69 @@
 Modify 5.1(5/2)
 add "parallel_block_statement" to the list of compound statements
 
-Modify 5.5(3/3)
+Replace 5.5(3/3)
 
 Iteration_scheme ::= while condition
    | [parallel] for loop_parameter_specification
    | [parallel] for iterator_specification
 
+Add after 5.5(6/5)
+
 {Legality Rules}
 A loop_statement shall not have both reserve words reverse and parallel present.
 
-A loop_statement with the *parallel* reserve word shall not update variables global
-to the loop unless either the action is sequential (see 9.10(11)), or the 
+A loop_statement with the *parallel* reserve word shall not update variables
+global to the loop unless either the action is sequential (see 9.10), or the
 expression for the update mentions the loop parameter.
+
+The sequence_of_statements of a loop_statement with the *parallel* reserved word
+shall not consist of a statement that can invoke a potentially blocking
+operation (see 9.5).
 
-The sequence_of_statements of a loop_statement with the *parallel* reserve word
-shall not consist of a statement that can invoke a potentially blocking operation (see 9.5(25)).
+Add after 5.5(7)
 
-Modify to 5.5(9/4)
+When the reserved word parallel is present and a transfer of control out of the
+loop occurs, an attempt is made to cancel further parallel execution of the
+sequence_of_statements that has not yet started. The completion of a
+loop_statement for a transfer of control out of the loop is delayed until all
+parallel execution of the sequence_of_statements is complete. If a transfer of
+control out of the loop occurs in multiple parallel executions of the
+sequence_of_statements then only the run time action of the first encountered
+transfer of control occurs.
 
-"For the execution of a loop_statement with the iteration_scheme being for
- loop_parameter_specification, the loop_parameter_specification is first
- elaborated. This elaboration creates {objects of} the loop parameter and 
- elaborates the discrete_subtype_definition. {If the keyword parallel is present,
- multiple objects of the loop parameter are created where each iteration is 
- associated with a specific loop parameter object, otherwise a single loop
- parameter object is created. Each loop parameter object is associated with a 
- thread of control where each thread proceeds independently and concurrently 
- between the points where they interact with other tasks and with each other.} 
- If the discrete_subtype_definition defines a subtype with a null range, the 
- execution of the loop_statement is complete. Otherwise, the sequence_of_statements 
- is executed once for each value of the discrete subtype defined by the 
- discrete_subtype_definition that satisfies the predicates of the subtype (or 
- until the loop is left as a consequence of a transfer of control).
- Prior to each such iteration, the corresponding value of the discrete subtype
- is assigned to [the]{a} loop parameter {object}. These values are assigned in 
- increasing order unless the reserved word reverse is present, in which case the 
- values are assigned in decreasing order {, or unless the reserved word parallel 
- is present, in which case the order is arbitrary}. "
+Modify 5.5(9/4)
 
+For the execution of a loop_statement with the iteration_scheme being for
+loop_parameter_specification, the loop_parameter_specification is first
+elaborated. This elaboration creates {objects of} the loop parameter and
+elaborates the discrete_subtype_definition. {If the keyword parallel is present,
+multiple objects of the loop parameter are created where each iteration is
+associated with a specific loop parameter object, otherwise a single loop
+parameter object is created. Each loop parameter object is associated with a
+thread of control where each thread proceeds independently and concurrently
+between the points where they interact with other tasks and with each other.} If
+the discrete_subtype_definition defines a subtype with a null range, the
+execution of the loop_statement is complete. Otherwise, the
+sequence_of_statements is executed once for each value of the discrete subtype
+defined by the discrete_subtype_definition that satisfies the predicates of the
+subtype (or until the loop is left as a consequence of a transfer of control).
+Prior to each such iteration, the corresponding value of the discrete subtype is
+assigned to [the]{a} loop parameter {object}. These values are assigned in
+increasing order unless the reserved word reverse is present, in which case the
+values are assigned in decreasing order {, or unless the reserved word parallel
+is present, in which case the order is arbitrary}.
+
 AARM - An implementation should statically treat the
 sequence_of_statements as being executed by separate threads of control,
 but whether they actually execute in parallel or sequentially should be a
 determination that is made dynamically at run time, dependent on factors
 such as the available computing resources.
 
-New paragraph after 5.5 (9/4)
+Add after 5.5(9/4)
 
 For a parallel loop, a check is made that updates to a component of a global
 array or to an element of a container via an expression that mentions the loop
-parameter sequential. See 9.10(11).
+parameter sequential. See 9.10.
 
 AARM Reason:
 The check ensures that different tasklets executing iterations of the same loop
@@ -217,19 +231,8 @@
 statically be determined that each iteration of the loop accesses a unique set
 of array components or container elements via the loop parameter.
 
-Add New paragraph after 5.5 (7)
+Add after 5.5(21)
 
-When the reserved word parallel is present and a transfer of control out of the
-loop occurs, an attempt is made to cancel further parallel execution of the
-sequence_of_statements that has not yet started. The completion of a 
-loop_statement for a transfer of control out of the loop is delayed until all 
-parallel execution of the sequence_of_statements is complete. If a transfer of 
-control out of the loop occurs in multiple parallel executions of the 
-sequence_of_statements then only the run time action of the first encountered 
-transfer of control occurs.
-
-Examples after 5.5(21)
-
 Example of a parallel loop
 
 -- See 3.6(30/2)
@@ -237,12 +240,8 @@
 for I in Grid(1)'Range loop
    Grid(I, 1) := (for all J in Grid(2)'Range => Grid(I,J) = True);
 end loop;
-
-Add after 5.5.1 (1/3)
 
-with Ada.Containers;
-
-Add after 5.5.1 (4/3)
+Add after 5.5.1(4/3)
 
    type Chunk_Array is limited interface
      with Nonblocking;
@@ -273,223 +272,235 @@
    type Parallel_Reversible_Iterator is limited interface
      and Parallel_Iterator and Reversible_Iterator
        with Nonblocking;
-      
-Modify 5.5.1 (6/3)
+
+Modify 5.5.1(6/3)
 
-An iterator type is a type descended from the Forward_Iterator 
-interface from some instance of Ada.Iterator_Interfaces. A reversible iterator 
-type is a type descended from the Reversible_Iterator interface from some 
-instance of Ada.Iterator_Interfaces. {A parallel iterator type is a type 
-descended from the Parallel_Iterator interface from some instance of 
+An iterator type is a type descended from the Forward_Iterator
+interface from some instance of Ada.Iterator_Interfaces. A reversible iterator
+type is a type descended from the Reversible_Iterator interface from some
+instance of Ada.Iterator_Interfaces. {A parallel iterator type is a type
+descended from the Parallel_Iterator interface from some instance of
 Ada.Iterator_Interfaces. A parallel reversible iterator type is a type
 descended from both the Parallel_Iterator interace and the Reversible_Iterator
 interface from some instance of Ada.Iterator_Interfaces.} An iterator object is
-an object of an iterator type. A reversible iterator object is an object of a 
-reversible iterator type. { A parallel iterator object is an object of a parallel 
-iterator type. A parallel reversible iterator object is an object of a 
-parallel reversible iterator type.} The formal subtype Cursor from the associated 
-instance of Ada.Iterator_Interfaces is the iteration cursor subtype for the iterator type.
-      
-Modify 5.5.1 (11/3)
-
-An iterable container type is an indexable container type with specified 
-Default_Iterator and Iterator_Element aspects. A reversible iterable container 
-type is an iterable container type with the default iterator type being a 
-reversible iterator type. {A parallel iterable container type is an iterable 
+an object of an iterator type. A reversible iterator object is an object of a
+reversible iterator type. { A parallel iterator object is an object of a
+parallel iterator type. A parallel reversible iterator object is an object of a
+parallel reversible iterator type.} The formal subtype Cursor from the
+associated instance of Ada.Iterator_Interfaces is the iteration cursor subtype
+for the iterator type.
+
+Modify 5.5.1(11/3)
+
+An iterable container type is an indexable container type with specified
+Default_Iterator and Iterator_Element aspects. A reversible iterable container
+type is an iterable container type with the default iterator type being a
+reversible iterator type. {A parallel iterable container type is an iterable
 container type with the default iterator type being a parallel iterator type. A
-parallel reversible iterable container type is an iterable container type with the
-default iterator type being a parallel reversible iterator type.} 
-An iterable container object is an object of an iterable container type. A 
-reversible iterable container object is an object of a reversible iterable 
-container type. {A parallel iterable container object is an object of a parallel 
+parallel reversible iterable container type is an iterable container type with
+the default iterator type being a parallel reversible iterator type.} An
+iterable container object is an object of an iterable container type. A
+reversible iterable container object is an object of a reversible iterable
+container type. {A parallel iterable container object is an object of a parallel
 iterable container type. A parallel reversible iterable container object is an
 object of a parallel reversible iterable container type.}
 
-Modify 5.5.2 (4/3)
+Modify 5.5.2(4/3)
 
-If the reserved word reverse appears, the iterator_specification is a reverse 
-iterator[.;] {If the reserved word parallel appears, the iterator_specification 
-is a parallel iterator;} otherwise it is a forward iterator. In a reverse 
-generalized iterator, the iterator_name shall be of a reversible iterator type. 
-{In a parallel generalized iterator, the iterator_name shall be of a parallel 
-iterator type.} In a reverse container element iterator, the default 
-iterator type for the type of the iterable_name shall be a reversible iterator 
-type. {In a parallel container element iterator, the default iterator type for 
+If the reserved word reverse appears, the iterator_specification is a reverse
+iterator[.;] {If the reserved word parallel appears, the iterator_specification
+is a parallel iterator;} otherwise it is a forward iterator. In a reverse
+generalized iterator, the iterator_name shall be of a reversible iterator type.
+{In a parallel generalized iterator, the iterator_name shall be of a parallel
+iterator type.} In a reverse container element iterator, the default
+iterator type for the type of the iterable_name shall be a reversible iterator
+type. {In a parallel container element iterator, the default iterator type for
 the type of the iterable_name shall be of a parallel iterator type.}
 
-Modify 5.5.2 (7/5)
+Modify 5.5.2(7/5)
 
-An iterator_specification declares a {set of} loop parameter {objects. If the 
- keyword parallel is present, multiple objects of the loop parameter are 
- created where each iteration is associated with a specific loop parameter 
- object; otherwise a single loop parameter object is created for the loop. Each 
- loop parameter object is associated with a thread of control where each thread 
- of control proceeds independently and concurrently between the points 
- where they interact with other tasks and with each other}. In a generalized 
- iterator, an array component iterator, or a container element iterator, 
- if a loop_parameter_subtype_indication is present, it determines the nominal 
- subtype of the loop parameter{s}. In a generalized iterator, if a 
- loop_parameter_subtype_indication is not present, the nominal subtype of the 
- loop parameter{s} is the iteration cursor subtype. In an array component 
- iterator, if a loop_parameter_subtype_indication is not present, the nominal 
- subtype of the loop parameter{s are}[ is] the component subtype of the type of 
- the iterable_name. In a container element iterator, if a 
- loop_parameter_subtype_indication is not present, the nominal subtype of the 
- loop parameter{s are}[is] the default element subtype for the type of the iterable_name.
-
-Modify 5.5.2 (8/3)
-In a generalized iterator, the loop parameter{s are} [is a] constant. In an 
-array component iterator, the loop parameter{s are} [is a] constant if the 
-iterable_name denotes a constant; otherwise [it]{they} denote[s] a variable. 
-In a container element iterator, the loop parameter{s are}[is a] constant if the 
-iterable_name denotes a constant, or if the Variable_Indexing aspect is not 
+An iterator_specification declares a {set of} loop parameter {objects. If the
+keyword parallel is present, multiple objects of the loop parameter are
+created where each iteration is associated with a specific loop parameter
+object; otherwise a single loop parameter object is created for the loop. Each
+loop parameter object is associated with a thread of control where each thread
+of control proceeds independently and concurrently between the points
+where they interact with other tasks and with each other}. In a generalized
+iterator, an array component iterator, or a container element iterator,
+if a loop_parameter_subtype_indication is present, it determines the nominal
+subtype of the loop parameter{s}. In a generalized iterator, if a
+loop_parameter_subtype_indication is not present, the nominal subtype of the
+loop parameter{s} is the iteration cursor subtype. In an array component
+iterator, if a loop_parameter_subtype_indication is not present, the nominal
+subtype of the loop parameter{s are}[ is] the component subtype of the type of
+the iterable_name. In a container element iterator, if a
+loop_parameter_subtype_indication is not present, the nominal subtype of the
+loop parameter{s are}[is] the default element subtype for the type of the
+iterable_name.
+
+Modify 5.5.2(8/3)
+In a generalized iterator, the loop parameter{s are} [is a] constant. In an
+array component iterator, the loop parameter{s are} [is a] constant if the
+iterable_name denotes a constant; otherwise [it]{they} denote[s] a variable.
+In a container element iterator, the loop parameter{s are}[is a] constant if the
+iterable_name denotes a constant, or if the Variable_Indexing aspect is not
 specified for the type of the iterable_name; otherwise it is a variable.
-
-Modify 5.5.2 (8.a/5)
 
-Ramification: The loop parameter{s} of a generalized iterator {have}[has] the 
-same accessibility as the loop statement. This means that the loop parameter 
-object{s} {are}[is] finalized when the loop statement is left. ([It]{They} also 
-may be finalized as part of assigning a new value to the loop parameter{s}.) For array 
-component iterators, the loop parameter{s each} directly denotes an element of 
-the array and [has]{have} the accessibility of the associated array. For container 
-element iterators, the loop parameter{s each} denotes the result of [the]{an} 
-indexing function call (in the case of a constant indexing) or a generalized 
-reference thereof (in the case of a variable indexing). Roughly speaking, the 
-loop parameter{s have} [has] the accessibility level of a single iteration of 
-the loop. More precisely, the function result (or the generalized reference 
-thereof) is considered to be renamed in the declarative part of a notional block 
-statement which immediately encloses the loop's sequence_of_statements; the 
-accessibility of the loop parameter{s are} [is] that of the block statement.
-
-Modify 5.5.2 (10/3)
+Modify AARM 5.5.2(8.a/5)
 
-For a generalized iterator, the loop parameter{s are} [is] created, the 
-iterator_name is evaluated, and the denoted iterator object{s} become[s] the loop 
-iterator{s}. In a forward generalized iterator, the operation First of the 
-iterator type is called on the loop iterator, to produce the initial value for 
-the loop parameter. If the result of calling Has_Element on the initial value is 
-False, then the execution of the loop_statement is complete. Otherwise, the 
-sequence_of_statements is executed and then the Next operation of the iterator 
-type is called with the loop iterator and the current value of the loop 
-parameter to produce the next value to be assigned to the loop parameter. This 
-repeats until the result of calling Has_Element on the loop parameter is False, 
-or the loop is left as a consequence of a transfer of control. For a 
-reverse generalized iterator, the operations Last and Previous are called rather 
-than First and Next. 
-
-{For a parallel generalized iterator, the operation Iterations
-of the iterator type is called first to determine the number of iterations associated
-with the iterator. If the result of calling Iterations is 0, then the execution
-of the loop_statement is complete. Otherwise, the operation Split of
-the iterator type is then called on a loop iterator, with the Advised_Split parameter
-value set to a value determined by the implementation that indicates a recommendation
-for the number of loop parameter objects that should be created. The result of the
-call to Split is a Chunk_Array object that indicates the number of loop parameter
-objects to be created by the implementation, as well as the range of cursor values 
-to be uniquely associated with each loop parameter object. The number of loop parameters
-to be created is determined by calling Length operation of the Chunk_Array.
-The range of cursor values to be associated with each loop parameter is determined
-by calling the Start and Finish operation of the Chunk_Array object using an
-ordinal index value of the loop parameter object as the Index parameter for these calls.
-The result of calling the Start operation is the initial cursor value to be assigned
-to a given loop parameter object. The result of calling the Finish operation is the final
-cursor value to be iterated for a given loop parameter object. The 
-sequence_of_statements is executed for each loop parameter object and then the Next 
-operation of the iterator type is called with the loop iterator and the current value of the loop 
-parameter to produce the next value to be assigned to a given loop parameter. This 
-repeats until the value of the loop parameter is equal to the final cursor value associated
-with the given loop parameter, or the loop is left as a consequence of a transfer of control.}
+Ramification: The loop parameter{s} of a generalized iterator {have}[has] the
+same accessibility as the loop statement. This means that the loop parameter
+object{s} {are}[is] finalized when the loop statement is left. ([It]{They} also
+may be finalized as part of assigning a new value to the loop parameter{s}.) For
+array component iterators, the loop parameter{s each} directly denotes an
+element of the array and [has]{have} the accessibility of the associated array.
+For container element iterators, the loop parameter{s each} denotes the result
+of [the]{an} indexing function call (in the case of a constant indexing) or a
+generalized reference thereof (in the case of a variable indexing). Roughly
+speaking, the loop parameter{s have} [has] the accessibility level of a single
+iteration of the loop. More precisely, the function result (or the generalized
+reference thereof) is considered to be renamed in the declarative part of a
+notional block statement which immediately encloses the loop's
+sequence_of_statements; the accessibility of the loop parameter{s are} [is] that
+of the block statement.
+
+Modify 5.5.2(10/3)
+
+For a generalized iterator, the loop parameter{s are} [is] created, the
+iterator_name is evaluated, and the denoted iterator object{s} become[s] the
+loop iterator{s}. In a forward generalized iterator, the operation First of the
+iterator type is called on the loop iterator, to produce the initial value for
+the loop parameter. If the result of calling Has_Element on the initial value is
+False, then the execution of the loop_statement is complete. Otherwise, the
+sequence_of_statements is executed and then the Next operation of the iterator
+type is called with the loop iterator and the current value of the loop
+parameter to produce the next value to be assigned to the loop parameter. This
+repeats until the result of calling Has_Element on the loop parameter is False,
+or the loop is left as a consequence of a transfer of control. For a reverse
+generalized iterator, the operations Last and Previous are called rather than
+First and Next.
+
+Add after 5.5.2(10/3)
+
+For a parallel generalized iterator, the operation Iterations
+of the iterator type is called first to determine the number of iterations
+associated with the iterator. If the result of calling Iterations is 0, then the
+execution of the loop_statement is complete. Otherwise, the operation Split of
+the iterator type is then called on a loop iterator, with the Advised_Split
+parameter value set to a value determined by the implementation that indicates a
+recommendation for the number of loop parameter objects that should be created.
+The result of the call to Split is a Chunk_Array object that indicates the
+number of loop parameter objects to be created by the implementation, as well as
+the range of cursor values to be uniquely associated with each loop parameter
+object. The number of loop parameters to be created is determined by calling
+Length operation of the Chunk_Array. The range of cursor values to be associated
+with each loop parameter is determined by calling the Start and Finish operation
+of the Chunk_Array object using an ordinal index value of the loop parameter
+object as the Index parameter for these calls. The result of calling the Start
+operation is the initial cursor value to be assigned to a given loop parameter
+object. The result of calling the Finish operation is the final cursor value to
+be iterated for a given loop parameter object. The sequence_of_statements is
+executed for each loop parameter object and then the Next operation of the
+iterator type is called with the loop iterator and the current value of the loop
+parameter to produce the next value to be assigned to a given loop parameter.
+This repeats until the value of the loop parameter is equal to the final cursor
+value associated with the given loop parameter, or the loop is left as a
+consequence of a transfer of control.
 
 AARM Note
 
-The Advised_Split parameter value is only a recommendation by the implementation.
-A container implementation may choose to ignore that recommendation if a more
-optimal split can be determined. For instance, a tree based container might create
-the split based on the number of branches at the top levels of the tree.
-
-Modify 5.5.2 (10.a/4)
-
-Ramification: The loop parameter{s} of a generalized iterator [is a]{are} variable{s} 
-of which the user only has a constant view. It follows the normal rules for a 
-variable of its nominal subtype. In particular, if the nominal subtype is indefinite, 
-the variable is constrained by its initial value. Similarly, if the nominal subtype 
-is class-wide, the variable (like all variables) has the tag of the initial value. 
-Constraint_Error may be raised by a subsequent iteration if Next{, }[ or] Previous{, or Split} 
-return an object with a different tag or constraint. 
-
-Modify 5.5.2 (11/3)
-
-For an array component iterator, the iterable_name is evaluated and the denoted 
-array object becomes the array for the loop. If the array for the loop is a 
-null array, then the execution of the loop_statement is complete. Otherwise,
-the sequence_of_statements is executed with [the] loop parameter{s that collectively 
-denote} [denoting] each component of the array for the loop{. If 
-the iterator is not a parallel array component iterator, the loop is iterated} 
-using a canonical order of components, which is last dimension varying fastest 
-(unless the array has convention Fortran, in which case it is first dimension 
-varying fastest). For a forward array component iterator, the iteration starts 
-with the component whose index values are each the first in their index range, 
-and continues in the canonical order. For a reverse array component iterator, the 
-iteration starts with the component whose index values are each the last in their 
-index range, and continues in the reverse of the canonical order. {For a parallel 
-array component iterator, the order of iteration is arbitrary.} The loop iteration 
-proceeds until the sequence_of_statements has been executed for each component of 
-the array for the loop, or until the loop is left as a consequence of a transfer of 
-control.
-
-Modify 5.5.2 (12/3)
-
-For a container element iterator, the iterable_name is evaluated and the denoted 
-iterable container object becomes the iterable container object for the loop. 
-The default iterator function for the type of the iterable container object for 
-the loop is called on the iterable container object and the result is the loop 
-iterator. [An object] {Objects} of the default cursor subtype [is]{are} created 
+The Advised_Split parameter value is only a recommendation by the
+implementation. A container implementation may choose to ignore that
+recommendation if a more optimal split can be determined. For instance, a tree
+based container might create the split based on the number of branches at the
+top levels of the tree.
+
+Modify AARM 5.5.2(10.a/4)
+
+Ramification: The loop parameter{s} of a generalized iterator [is a]{are}
+variable{s} of which the user only has a constant view. It follows the normal
+rules for a variable of its nominal subtype. In particular, if the nominal
+subtype is indefinite, the variable is constrained by its initial value.
+Similarly, if the nominal subtype is class-wide, the variable (like all
+variables) has the tag of the initial value. Constraint_Error may be raised by a
+subsequent iteration if Next{, }[ or] Previous{, or Split} return an object with
+a different tag or constraint.
+
+Modify 5.5.2(11/3)
+
+For an array component iterator, the iterable_name is evaluated and the denoted
+array object becomes the array for the loop. If the array for the loop is a null
+array, then the execution of the loop_statement is complete. Otherwise, the
+sequence_of_statements is executed with [the] loop parameter{s that collectively
+denote} [denoting] each component of the array for the loop{. If the iterator is
+not a parallel array component iterator, the loop is iterated} using a canonical
+order of components, which is last dimension varying fastest (unless the array
+has convention Fortran, in which case it is first dimension varying fastest).
+For a forward array component iterator, the iteration starts with the component
+whose index values are each the first in their index range, and continues in the
+canonical order. For a reverse array component iterator, the iteration starts
+with the component whose index values are each the last in their index range,
+and continues in the reverse of the canonical order. {For a parallel array
+component iterator, the order of iteration is arbitrary.} The loop iteration
+proceeds until the sequence_of_statements has been executed for each component
+of the array for the loop, or until the loop is left as a consequence of a
+transfer of control.
+
+Modify 5.5.2(12/3)
+
+For a container element iterator, the iterable_name is evaluated and the denoted
+iterable container object becomes the iterable container object for the loop.
+The default iterator function for the type of the iterable container object for
+the loop is called on the iterable container object and the result is the loop
+iterator. [An object] {Objects} of the default cursor subtype [is]{are} created
 (the loop cursor{s}).
 
-Modify 5.5.2 (13/3)
+Modify 5.5.2(13/3) [into three paragraphs]
 
-For a forward container element iterator, the operation First of the iterator 
-type is called on the loop iterator, to produce the initial value for the loop 
-cursor. If the result of calling Has_Element on the initial value is False, then 
-the execution of the loop_statement is complete. Otherwise, the sequence_of_statements 
-is executed with the loop parameter denoting an indexing (see 4.1.6) into the 
-iterable container object for the loop, with the only parameter to the indexing 
-being the current value of the loop cursor; then the Next operation of the iterator 
-type is called with the loop iterator and the loop cursor to produce the next value 
-to be assigned to the loop cursor. This repeats until the result of calling 
-Has_Element on the loop cursor is False, or until the loop is left as a consequence 
-of a transfer of control. For a reverse container element iterator, the operations 
-Last and Previous are called rather than First and Next. 
-
-{For a parallel container element iterator, the operation Iterations is first called 
-to determine the number of iterations associated with the iterator. If the result of 
-calling Iterations is 0, then the execution of the loop_statement is complete. Otherwise,
-the operation Split of the iterator type is then called on a loop iterator, with the 
-Advised_Split parameter value set to a value determined by the implementation that 
-indicates a recommendation for the number of loop parameter objects that should be 
-created. The result of the call to Split is a Chunk_Array object that indicates 
-the number of loop parameter objects to be created by the implementation, as well 
-as the range of cursor values to be uniquely associated with each loop parameter 
-object. The number of loop parameters to be created is determined by calling the Length 
-operation of the Chunk_Array. The range of cursor values to be associated with each 
-loop parameter is determined by calling the Start and Finish operation of the 
-Chunk_Array object using an ordinal index value of the loop parameter object as 
-the Index parameter for these calls. The result of calling the Start operation is 
-the initial cursor value to be assigned to a given loop parameter object. The result 
-of calling the Finish operation is the final cursor value to be iterated for a given 
-loop parameter object. The sequence_of_statements is executed for each loop parameter 
-object and then the Next operation of the iterator type is called with the loop iterator 
-and the current value of the loop parameter to produce the next value to be assigned to a 
-given loop parameter. This repeats until the value of the loop parameter is equal to 
-the final cursor value associated with the given loop parameter, or the loop is left 
-as a consequence of a transfer of control.}
+For a forward container element iterator, the operation First of the iterator
+type is called on the loop iterator, to produce the initial value for the loop
+cursor. If the result of calling Has_Element on the initial value is False, then
+the execution of the loop_statement is complete. Otherwise, the
+sequence_of_statements is executed with the loop parameter denoting an indexing
+(see 4.1.6) into the iterable container object for the loop, with the only
+parameter to the indexing being the current value of the loop cursor; then the
+Next operation of the iterator type is called with the loop iterator and the
+loop cursor to produce the next value to be assigned to the loop cursor. This
+repeats until the result of calling Has_Element on the loop cursor is False, or
+until the loop is left as a consequence of a transfer of control. For a reverse
+container element iterator, the operations Last and Previous are called rather
+than First and Next.{
+
+For a parallel container element iterator, the operation Iterations is first
+called to determine the number of iterations associated with the iterator. If
+the result of calling Iterations is 0, then the execution of the loop_statement
+is complete. Otherwise, the operation Split of the iterator type is then called
+on a loop iterator, with the Advised_Split parameter value set to a value
+determined by the implementation that indicates a recommendation for the number
+of loop parameter objects that should be created. The result of the call to
+Split is a Chunk_Array object that indicates the number of loop parameter
+objects to be created by the implementation, as well as the range of cursor
+values to be uniquely associated with each loop parameter object. The number of
+loop parameters to be created is determined by calling the Length operation of
+the Chunk_Array. The range of cursor values to be associated with each loop
+parameter is determined by calling the Start and Finish operation of the
+Chunk_Array object using an ordinal index value of the loop parameter object as
+the Index parameter for these calls. The result of calling the Start operation
+is the initial cursor value to be assigned to a given loop parameter object. The
+result of calling the Finish operation is the final cursor value to be iterated
+for a given loop parameter object. The sequence_of_statements is executed for
+each loop parameter object and then the Next operation of the iterator type is
+called with the loop iterator and the current value of the loop parameter to
+produce the next value to be assigned to a given loop parameter. This repeats
+until the value of the loop parameter is equal to the final cursor value
+associated with the given loop parameter, or the loop is left as a consequence
+of a transfer of control.
 
-If the loop parameter is a constant  (see above), then the indexing uses the 
-default constant indexing function for the type of the iterable container object 
+}If the loop parameter is a constant  (see above), then the indexing uses the
+default constant indexing function for the type of the iterable container object
 for the loop; otherwise it uses the default variable indexing function.
 
-Modify 5.5.2 (15/3)
+Modify 5.5.2(15/3)
 
 -- Array component iterator example:
 {parallel}
@@ -497,11 +508,11 @@
    Element := Element * 2.0; -- Double each element of Board, a two-dimensional array.
 end loop;
 
-Add new Section 5.5.3
+Add a new subclause 5.5.3
 
-User-Defined Parallel Loop Chunking for Discrete Types
+5.5.3 User-Defined Parallel Loop Chunking for Discrete Types
 
-The following language-defined generic library package exists: 
+The following language-defined generic library package exists:
 
 with Ada.Iterator_Interfaces;
 with Ada.Containers;
@@ -537,15 +548,15 @@
    return Chunk_Array_Iterator_Interfaces.Chunk_Array'Class
      with Pre => Chunks <= Loop_Index'Pos(To) - Loop_Index'Pos(From) + 1;
 
-Split returns a Chunk_Array object (see 5.5.1) for user-defined parallel 
+Split returns a Chunk_Array object (see 5.5.1) for user-defined parallel
 iteration over a range of values of a discrete subtype starting with the value
-From and ending with the value To. The Chunks value indicates the number of Executors
-(see 9.12) to be associated with the parallel loop, which equals the value returned
-by calling the Length operation on the Chunk_Array result. 
+From and ending with the value To. The Chunks value indicates the number of
+Executors (see 9.12) to be associated with the parallel loop, which equals the
+value returned by calling the Length operation on the Chunk_Array result.
 
 Examples
 
-  declare     
+  declare
      package Manual_Chunking is new Ada.Discrete_Chunking (Integer);
 
      Chunks : constant
@@ -563,12 +574,14 @@
            for I in Chunks.Start(Chunk) .. Chunks.Finish(Chunk) loop
               Put_Line (Integer'Image(I) & "=" & Integer'Image (A(I));
            end loop;
-           
+
            Text_IO.Close(File);
         end;
      end loop;
   end;
 
+Add a new subclause
+
 5.6.1 Parallel Block Statements
 
 A parallel_block_statement encloses two or more handled_sequence_of_statements
@@ -586,14 +599,14 @@
    {and
       handled_sequence_of_statements}
     end do;
-    
+
 Legality Rules
 
 A parallel_block_statement shall not update variables global to the loop unless
-the action is sequential (see 9.10(11)).
+the action is sequential (see 9.10).
 
-A handled_sequence_of_statements of a parallel_block_statement shall not consist 
-of a statement that can invoke a potentially blocking operation (see 9.5(25)).
+A handled_sequence_of_statements of a parallel_block_statement shall not consist
+of a statement that can invoke a potentially blocking operation (see 9.5).
 
 Static Semantics
 
@@ -601,17 +614,18 @@
 proceeds independently and in parallel between the points where they
 interact with other tasks and with each other.
 
-For the execution of a parallel_block_statement, each handled_sequence_of_statements
-is executed once, until the parallel_block_statement is complete. The 
-parallel_block_statement is complete when all handled_sequence_of_statements have
-completed execution or when transfer of control occurs that transfers 
-control out of the parallel block. When a transfer of control out of the 
-parallel block occurs, an attempt is made to cancel further parallel execution of
-a handled_sequence_of_statements that have not yet started. The completion of a 
-parallel_block_statement for a transfer of control out 
-of the parallel block is delayed until all parallel execution of the handled_sequence_of_statements 
-is complete. If a transfer of control out of the loop occurs in multiple parallel
-executions of handled_sequence_of_statements then only the run time action of the first
+For the execution of a parallel_block_statement, each
+handled_sequence_of_statements is executed once, until the
+parallel_block_statement is complete. The parallel_block_statement is complete
+when all handled_sequence_of_statements have completed execution or when
+transfer of control occurs that transfers control out of the parallel block.
+When a transfer of control out of the parallel block occurs, an attempt is made
+to cancel further parallel execution of a handled_sequence_of_statements that
+have not yet started. The completion of a parallel_block_statement for a
+transfer of control out of the parallel block is delayed until all parallel
+execution of the handled_sequence_of_statements is complete. If a transfer of
+control out of the loop occurs in multiple parallel executions of
+handled_sequence_of_statements then only the run time action of the first
 encountered transfer of control out of the parallel block occurs.
 
 
@@ -654,14 +668,16 @@
       return X + Y;
    end Fibonacci;
 
-Change 9.10 (13)
+Modify 9.10(13)
 
-"Both actions occur as part of the execution of the same task {unless
- either are part of a;
+Both actions occur as part of the execution of the same task {unless
+either are part of a;
    - different handled_sequence_of_statements of a parallel block statement,
-   - sequence_of_statements of a parallel loop statement.}"
+   - sequence_of_statements of a parallel loop statement.}
+
+Add a new subclause 9.12
 
-New section 9.12 Executors and Tasklets
+9.12 Executors and Tasklets
 
 A task may distribute execution across different physical processors in
 parallel, where each execution is a separate thread of control that
@@ -673,131 +689,136 @@
 execution until all the executors have completed their respective
 executions.
 
-A parallel block statement or parallel loop statement may assign a set of 
+A parallel block statement or parallel loop statement may assign a set of
 executors to execute the construct, if extra computing resources are available.
 
-Add new paragraph after 11.5 (20)
+Add after 11.5(20)
 
 Loop_Parameter_Check
   For a parallel loop, check that updates to a component of an array or to an
-  element of a container via the loop parameter are sequential. See 9.10(11). 
+  element of a container via the loop parameter are sequential. See 9.10.
 
 Modify A.18.2(74.1/3)
 
 function Iterate (Container : in Vector)
       return Vector_Iterator_Interfaces.{Parallel_}Reversible_Iterator'Class;
 
-Modify A.18.2 (74.2/3)
+Modify A.18.2(74.2/3)
 
 function Iterate (Container : in Vector; Start : in Cursor)
       return Vector_Iterator_Interfaces.{Parallel_}Reversible_Iterator'Class;
 
-Modify A.18.2 (230.1/3)
+Modify A.18.2(230.1/3)
 
 function Iterate (Container : in Vector)
    return Vector_Iterator_Interfaces.{Parallel_}Reversible_Iterator'Class;
 
-Modify A.18.2 (230.2/3)
+Modify A.18.2(230.2/3)
 
-Iterate returns a {parallel} reversible iterator object (see 5.5.1) that will 
-generate a value for [a] loop parameter{s} (see 5.5.2) designating each node in 
-Container, starting with the first node and moving the cursor as per the Next 
-function when used as a forward iterator, and starting with the last node and 
+Iterate returns a {parallel} reversible iterator object (see 5.5.1) that will
+generate a value for [a] loop parameter{s} (see 5.5.2) designating each node in
+Container, starting with the first node and moving the cursor as per the Next
+function when used as a forward iterator, and starting with the last node and
 moving the cursor as per the Previous function when used as a reverse iterator
 {, and starting with all nodes simultaneously using the Split function
-to generate cursors for all the iterations of the loop when used as a parallel 
-iterator}. Tampering with the cursors of Container is prohibited while the 
-iterator object exists (in particular, in the sequence_of_statements of the 
-loop_statement whose iterator_specification denotes this object). The iterator 
+to generate cursors for all the iterations of the loop when used as a parallel
+iterator}. Tampering with the cursors of Container is prohibited while the
+iterator object exists (in particular, in the sequence_of_statements of the
+loop_statement whose iterator_specification denotes this object). The iterator
 object needs finalization.
 
-Modify A.18.2 (230.3/3)
+Modify A.18.2(230.3/3)
 
 function Iterate (Container : in Vector; Start : in Cursor)
    return Vector_Iterator_Interfaces.{Parallel_}Reversible_Iterator'Class;
 
-Modify A.18.2 (230.4/3)
+Modify A.18.2(230.4/3)
 
-If Start is not No_Element and does not designate an item in Container, then 
-Program_Error is propagated. If Start is No_Element, then Constraint_Error is 
-propagated. Otherwise, Iterate returns a {parallel }reversible iterator object 
-(see 5.5.1) that will generate a value for [a] loop parameter{s} (see 5.5.2) 
-designating each node in Container, starting with the node designated by Start 
-and moving the cursor as per the Next function when used as a forward iterator, 
-or moving the cursor as per the Previous function when used as a reverse iterator
-{, or all nodes simultaneously using the Split function when used as a parallel 
-iterator}. Tampering with the cursors of Container is prohibited while the iterator 
-object exists (in particular, in the sequence_of_statements of the loop_statement whose 
-iterator_specification denotes this object). The iterator object needs finalization.
+If Start is not No_Element and does not designate an item in Container, then
+Program_Error is propagated. If Start is No_Element, then Constraint_Error is
+propagated. Otherwise, Iterate returns a {parallel }reversible iterator object
+(see 5.5.1) that will generate a value for [a] loop parameter{s} (see 5.5.2)
+designating each node in Container, starting with the node designated by Start
+and moving the cursor as per the Next function when used as a forward iterator,
+or moving the cursor as per the Previous function when used as a reverse
+iterator {, or all nodes simultaneously using the Split function when used as a
+parallel iterator}. Tampering with the cursors of Container is prohibited while
+the iterator object exists (in particular, in the sequence_of_statements of the
+loop_statement whose iterator_specification denotes this object). The iterator
+object needs finalization.
 
-Modify A.18.3 (46.1/3)
+Modify A.18.3(46.1/3)
 
 function Iterate (Container : in List)
       return List_Iterator_Interfaces.{Parallel_}Reversible_Iterator'Class;
 
-Modify A.18.3 (46.2/3)
+Modify A.18.3(46.2/3)
 
 function Iterate (Container : in List; Start : in Cursor)
       return List_Iterator_Interfaces.{Parallel_}Reversible_Iterator'Class;
 
-Modify A.18.3 (144.1/3)
+Modify A.18.3(144.1/3)
 
 function Iterate (Container : in List)
    return List_Iterator_Interfaces.{Parallel_}Reversible_Iterator'Class;
 
-Modify A.18.3 (144.2/3)
+Modify A.18.3(144.2/3)
 
-Iterate returns a {parallel }reversible iterator object (see 5.5.1) that will 
-generate a value for [a] loop parameter{s} (see 5.5.2) designating each node in 
-Container, starting with the first node and moving the cursor as per the Next 
-function when used as a forward iterator, and starting with the last node and 
+Iterate returns a {parallel }reversible iterator object (see 5.5.1) that will
+generate a value for [a] loop parameter{s} (see 5.5.2) designating each node in
+Container, starting with the first node and moving the cursor as per the Next
+function when used as a forward iterator, and starting with the last node and
 moving the cursor as per the Previous function when used as a reverse iterator
-{, and starting with all nodes simultaneously using the Split function
-to generate cursors for all the iterations of the loop when used as a parallel
-iterator}. Tampering with the cursors of Container is prohibited while the iterator 
-object exists (in particular, in the sequence_of_statements of the loop_statement 
-whose iterator_specification denotes this object). The iterator object needs finalization.
+{, and starting with all nodes simultaneously using the Split function to
+generate cursors for all the iterations of the loop when used as a parallel
+iterator}. Tampering with the cursors of Container is prohibited while the
+iterator object exists (in particular, in the sequence_of_statements of the
+loop_statement whose iterator_specification denotes this object). The iterator
+object needs finalization.
 
-Modify A.18.3 (144.3/3)
+Modify A.18.3(144.3/3)
 
 function Iterate (Container : in List; Start : in Cursor)
    return List_Iterator_Interfaces.Parallel_Reversible_Iterator'Class;
 
-Modify A.18.3 (144.4/3)
+Modify A.18.3(144.4/3)
 
-If Start is not No_Element and does not designate an item in Container, then 
-Program_Error is propagated. If Start is No_Element, then Constraint_Error is 
-propagated. Otherwise, Iterate returns a {parallel} reversible iterator object 
-(see 5.5.1) that will generate [a] value{s} for [a] loop parameter{s} (see 5.5.2) 
-designating each node in Container, starting with the node designated by Start 
-and moving the cursor as per the Next function when used as a forward iterator, 
-or moving the cursor as per the Previous function when used as a reverse iterator
-{or all nodes simultaneously using the Split function when used as a parallel iterator}.
-Tampering with the cursors of Container is prohibited while the iterator object exists (in 
-particular, in the sequence_of_statements of the loop_statement whose 
-iterator_specification denotes this object). The iterator object needs finalization.
+If Start is not No_Element and does not designate an item in Container, then
+Program_Error is propagated. If Start is No_Element, then Constraint_Error is
+propagated. Otherwise, Iterate returns a {parallel} reversible iterator object
+(see 5.5.1) that will generate [a] value{s} for [a] loop parameter{s} (see
+5.5.2) designating each node in Container, starting with the node designated by
+Start and moving the cursor as per the Next function when used as a forward
+iterator, or moving the cursor as per the Previous function when used as a
+reverse iterator {or all nodes simultaneously using the Split function when used
+as a parallel iterator}. Tampering with the cursors of Container is prohibited
+while the iterator object exists (in particular, in the sequence_of_statements
+of the loop_statement whose iterator_specification denotes this object). The
+iterator object needs finalization.
 
-Modify A.18.5 (37.1/3)
+Modify A.18.5(37.1/3)
 
 function Iterate (Container : in Map)
       return Map_Iterator_Interfaces.{Parallel_}[Forward_]Iterator'Class;
 
-Modify A.18.5 (61.1/3)
+Modify A.18.5(61.1/3)
 
 function Iterate (Container : in Map)
    return Map_Iterator_Interfaces.{Parallel}[Forward]_Iterator'Class;
 
-Modify A.18.5 (61.2/3)
-Iterate returns a[n] {parallel} iterator object (see 5.5.1) that will generate [a] 
-value{s} for [a] loop parameter{s} (see 5.5.2) designating each node in Container, starting 
-with the first node and moving the cursor according to the successor relation 
-{when used as a forward iterator, and starting with all nodes simultaneously using 
-the Split function to generate cursors for all the iterations of the loop 
-when used as a parallel iterator}. Tampering with the cursors of Container is 
-prohibited while the iterator object exists (in particular, in the 
-sequence_of_statements of the loop_statement whose iterator_specification denotes 
-this object). The iterator object needs finalization.
+Modify A.18.5(61.2/3)
 
+Iterate returns a[n] {parallel} iterator object (see 5.5.1) that will generate
+[a] value{s} for [a] loop parameter{s} (see 5.5.2) designating each node in
+Container, starting with the first node and moving the cursor according to the
+successor relation {when used as a forward iterator, and starting with all nodes
+simultaneously using the Split function to generate cursors for all the
+iterations of the loop when used as a parallel iterator}. Tampering with the
+cursors of Container is prohibited while the iterator object exists (in
+particular, in the sequence_of_statements of the loop_statement whose
+iterator_specification denotes this object). The iterator object needs
+finalization.
+
 Modify A.18.6(51.1/3)
 
 function Iterate (Container : in Map)
@@ -815,17 +836,17 @@
 
 Modify A.18.6(94.2/3)
 
- Iterate returns a {parallel} reversible iterator object (see 5.5.1) that will 
- generate [a] value{s} for [a] loop parameter{s} (see 5.5.2) designating each 
- node in Container, starting with the first node and moving the cursor according 
- to the successor relation when used as a forward iterator, and starting with the 
- last node and moving the cursor according to the predecessor relation when used 
- as a reverse iterator {, and starting with all nodes simultaneously using the 
- Split function to generate cursors for all the iterations of the loop 
- when used as a parallel iterator}. Tampering with the cursors of Container is 
- prohibited while the iterator object exists (in particular, in the 
- sequence_of_statements of the loop_statement whose iterator_specification denotes 
- this object). The iterator object needs finalization.
+Iterate returns a {parallel} reversible iterator object (see 5.5.1) that will
+generate [a] value{s} for [a] loop parameter{s} (see 5.5.2) designating each
+node in Container, starting with the first node and moving the cursor according
+to the successor relation when used as a forward iterator, and starting with the
+last node and moving the cursor according to the predecessor relation when used
+as a reverse iterator {, and starting with all nodes simultaneously using the
+Split function to generate cursors for all the iterations of the loop when used
+as a parallel iterator}. Tampering with the cursors of Container is prohibited
+while the iterator object exists (in particular, in the sequence_of_statements
+of the loop_statement whose iterator_specification denotes this object). The
+iterator object needs finalization.
 
 Modify A.18.6(94.3/3)
 
@@ -834,18 +855,18 @@
 
 Modify A.18.6(94.4/3)
 
-If Start is not No_Element and does not designate an item in Container, then 
-Program_Error is propagated. If Start is No_Element, then Constraint_Error is 
-propagated. Otherwise, Iterate returns a {parallel} reversible iterator object 
-(see 5.5.1) that will generate [a] value{s} for [a] loop parameter{s} (see 5.5.2) 
-designating each node in Container, starting with the node designated by Start 
-and moving the cursor according to the successor relation when used as a forward 
-iterator, or moving the cursor according to the predecessor relation when used as 
-a reverse iterator {, or all nodes simultaneously using the Split function when used 
-as a parallel iterator}. Tampering with the cursors of Container is prohibited 
-while the iterator object exists (in particular, in the sequence_of_statements 
-of the loop_statement whose iterator_specification denotes this object). The 
-iterator object needs finalization.
+If Start is not No_Element and does not designate an item in Container, then
+Program_Error is propagated. If Start is No_Element, then Constraint_Error is
+propagated. Otherwise, Iterate returns a {parallel} reversible iterator object
+(see 5.5.1) that will generate [a] value{s} for [a] loop parameter{s} (see
+5.5.2) designating each node in Container, starting with the node designated by
+Start and moving the cursor according to the successor relation when used as a
+forward iterator, or moving the cursor according to the predecessor relation
+when used as a reverse iterator {, or all nodes simultaneously using the Split
+function when used as a parallel iterator}. Tampering with the cursors of
+Container is prohibited while the iterator object exists (in particular, in the
+sequence_of_statements of the loop_statement whose iterator_specification
+denotes this object). The iterator object needs finalization.
 
 Modify A.18.8(49.1/3)
 
@@ -859,15 +880,16 @@
 
 Modify A.18.8(85.2/3)
 
-Iterate returns a[n] {parallel} iterator object (see 5.5.1) that will generate 
-[a] value{s} for [a] loop parameter{s} (see 5.5.2) designating each element in 
-Container, starting with the first element and moving the cursor according to the 
-successor relation {when used as a forward iterator, and starting with all nodes 
-simultaneously using the Split function to generate cursors for all the 
-iterations of the loop when used as a parallel iterator.} Tampering with the 
-cursors of Container is prohibited while the iterator object exists (in 
-particular, in the sequence_of_statements of the loop_statement whose 
-iterator_specification denotes this object). The iterator object needs finalization.
+Iterate returns a[n] {parallel} iterator object (see 5.5.1) that will generate
+[a] value{s} for [a] loop parameter{s} (see 5.5.2) designating each element in
+Container, starting with the first element and moving the cursor according to
+the successor relation {when used as a forward iterator, and starting with all
+nodes simultaneously using the Split function to generate cursors for all the
+iterations of the loop when used as a parallel iterator.} Tampering with the
+cursors of Container is prohibited while the iterator object exists (in
+particular, in the sequence_of_statements of the loop_statement whose
+iterator_specification denotes this object). The iterator object needs
+finalization.
 
 Modify A.18.9(61.1/3)
 
@@ -886,17 +908,18 @@
 
 Modify A.18.9(113.2/3)
 
-Iterate returns a {parallel} reversible iterator object (see 5.5.1) that will 
-generate [a] value{s} for [a] loop parameter{s} (see 5.5.2) designating each element 
-in Container, starting with the first element and moving the cursor according to 
-the successor relation when used as a forward iterator, and starting with the 
-last element and moving the cursor according to the predecessor relation when 
-used as a reverse iterator {, and starting with all nodes simultaneously using the 
- Split function to generate cursors for all the iterations of the loop 
- when used as a parallel iterator}. Tampering with the cursors of Container is 
- prohibited while the iterator object exists (in particular, in the 
- sequence_of_statements of the loop_statement whose iterator_specification 
- denotes this object). The iterator object needs finalization.
+Iterate returns a {parallel} reversible iterator object (see 5.5.1) that will
+generate [a] value{s} for [a] loop parameter{s} (see 5.5.2) designating each
+element in Container, starting with the first element and moving the cursor
+according to the successor relation when used as a forward iterator, and
+starting with the last element and moving the cursor according to the
+predecessor relation when used as a reverse iterator {, and starting with all
+nodes simultaneously using the Split function to generate cursors for all the
+iterations of the loop when used as a parallel iterator}. Tampering with the
+cursors of Container is prohibited while the iterator object exists (in
+particular, in the sequence_of_statements of the loop_statement whose
+iterator_specification denotes this object). The iterator object needs
+finalization.
 
 Modify A.18.9(113.3/3)
 
@@ -905,18 +928,18 @@
 
 Modify A.18.9(113.4/3)
 
-If Start is not No_Element and does not designate an item in Container, then 
-Program_Error is propagated. If Start is No_Element, then Constraint_Error is 
-propagated. Otherwise, Iterate returns a {parallel} reversible iterator object 
-(see 5.5.1) that will generate [a] value{s} for [a] loop parameter{s} (see 5.5.2) 
-designating each element in Container, starting with the element designated by 
-Start and moving the cursor according to the successor relation when used as a 
-forward iterator, or moving the cursor according to the predecessor relation when 
-used as a reverse iterator {, or all nodes simultaneously using the Split function 
-when used as a parallel iterator}. Tampering with the cursors of Container is prohibited 
-while the iterator object exists (in particular, in the sequence_of_statements 
-of the loop_statement whose iterator_specification denotes this object). The 
-iterator object needs finalization.
+If Start is not No_Element and does not designate an item in Container, then
+Program_Error is propagated. If Start is No_Element, then Constraint_Error is
+propagated. Otherwise, Iterate returns a {parallel} reversible iterator object
+(see 5.5.1) that will generate [a] value{s} for [a] loop parameter{s} (see 5.5.2)
+designating each element in Container, starting with the element designated by
+Start and moving the cursor according to the successor relation when used as a
+forward iterator, or moving the cursor according to the predecessor relation
+when used as a reverse iterator {, or all nodes simultaneously using the Split
+function when used as a parallel iterator}. Tampering with the cursors of
+Container is prohibited while the iterator object exists (in particular, in the
+sequence_of_statements of the loop_statement whose iterator_specification
+denotes this object). The iterator object needs finalization.
 
 Modify A.18.10(44/3)
 
@@ -935,15 +958,16 @@
 
 Modify A.18.10(157/4)
 
-Iterate returns a[n] {parallel} iterator object (see 5.5.1) that will generate 
-[a] value{s} for [a] loop parameter{s} (see 5.5.2) designating each element node 
-in Container, starting from with the root node and proceeding in a depth-first order
-{when used as a forward_iterator, and starting with all nodes 
-simultaneously using the Split function to generate cursors for all the 
-iterations of the loop when used as a parallel iterator}. Tampering with the 
-cursors of Container is prohibited while the iterator object exists (in particular, 
-in the sequence_of_statements of the loop_statement whose iterator_specification 
-denotes this object). The iterator object needs finalization.
+Iterate returns a[n] {parallel} iterator object (see 5.5.1) that will generate
+[a] value{s} for [a] loop parameter{s} (see 5.5.2) designating each element node
+in Container, starting from with the root node and proceeding in a depth-first
+order {when used as a forward_iterator, and starting with all nodes
+simultaneously using the Split function to generate cursors for all the
+iterations of the loop when used as a parallel iterator}. Tampering with the
+cursors of Container is prohibited while the iterator object exists (in
+particular, in the sequence_of_statements of the loop_statement whose
+iterator_specification denotes this object). The iterator object needs
+finalization.
 
 Modify A.18.10(158/3)
 
@@ -952,21 +976,21 @@
 
 Modify A.18.10(159/3)
 
-If Position equals No_Element, then Constraint_Error is propagated. Otherwise, 
-Iterate_Subtree returns a[n] {parallel} iterator object (see 5.5.1) that will 
-generate [a] value{s} for [a] loop parameter{s} (see 5.5.2) designating each 
-element in the subtree rooted by the node designated by Position, starting from 
-with the node designated by Position and proceeding in a depth-first order 
-{when used as a forward iterator, or all nodes simultaneously using the Split 
- function when used as a parallel iterator}. If Position 
- equals No_Element, then Constraint_Error is propagated. Tampering with the cursors 
- of the container that contains the node designated by Position is prohibited while 
- the iterator object exists (in particular, in the sequence_of_statements of the 
- loop_statement whose iterator_specification denotes this object). The iterator 
- object needs finalization.
+If Position equals No_Element, then Constraint_Error is propagated. Otherwise,
+Iterate_Subtree returns a[n] {parallel} iterator object (see 5.5.1) that will
+generate [a] value{s} for [a] loop parameter{s} (see 5.5.2) designating each
+element in the subtree rooted by the node designated by Position, starting from
+with the node designated by Position and proceeding in a depth-first order {when
+used as a forward iterator, or all nodes simultaneously using the Split function
+when used as a parallel iterator}. If Position equals No_Element, then
+Constraint_Error is propagated. Tampering with the cursors of the container that
+contains the node designated by Position is prohibited while the iterator object
+exists (in particular, in the sequence_of_statements of the loop_statement whose
+iterator_specification denotes this object). The iterator object needs
+finalization.
 
 
-Add C.7.1 (5.1)
+Add after C.7.1(5)
 
 The Task_Id value associated with each handled_sequence_of_statements of a
 parallel_block_statement, or of each sequence_of_statements of a parallel loop
@@ -976,7 +1000,7 @@
 sequence_of_statements of a parallel loop are treated as though they are all
 executing as the task that encountered the parallel construct.
 
-Add after D.16 (5/3)
+Add after D.16(5/3)
 
    type Iteration_Count is range 0 .. implementation-defined;
    for Iteration_Count'Size use implementation-defined;
@@ -987,14 +1011,14 @@
      (Iterations :  Iteration_Count) return Split_Count
        witn Non_Blocking => False;
 
-Add after D.16 (8/3)
+Add after D.16(8/3)
 
 The Advised_Split_Count function accepts a parameter that indicates the number
-of iterations associated with a parallel loop, and returns a recommended value 
-for the number of loop parameter objects to be associated with a parallel loop 
-statement. Such a value is intended to be passed as an actual for the 
-Advised_Split parameter of the Split operation associated with a parallel iterator 
-object (See 5.5.1).
+of iterations associated with a parallel loop, and returns a recommended value
+for the number of loop parameter objects to be associated with a parallel loop
+statement. Such a value is intended to be passed as an actual for the
+Advised_Split parameter of the Split operation associated with a parallel
+iterator object (see 5.5.1).
 
 !discussion
 
@@ -1080,7 +1104,7 @@
 We considered allowing the parallel block construct to be preceded with an
 optional declare part, but it was observed that it was more likely to be useful
 to have objects that are shared across multiple parallel sequences to outlive
-the parallel block.  Therefore we reverted to the simpler syntax proposed
+the parallel block. Therefore we reverted to the simpler syntax proposed
 above. Because there are no local declarations, there was
 also no point in having a statement_identifier (block label) for a
 parallel block. Allowing an exit statement to replace a goto that targets the
@@ -1095,12 +1119,12 @@
 statement in a parallel block, it could be the subject of a separate AI.
 
 We considered what the semantics might be for a parallel block if the parallel
-keyword were absent. This might be a good syntactic construct to use for 
+keyword were absent. This might be a good syntactic construct to use for
 supporting coroutines, for example. Rather than deal with that question in this
 AI, we leave that for consideration in separate AI's.
 
 We considered whether blocking calls should be allowed in a parallel block
-statement. We felt that allowing that could add significant complexity for 
+statement. We felt that allowing that could add significant complexity for
 the implementor, as well as introduce safety concerns about potential deadlocking.
 While such a capability is possible, it was felt that it should be disallowed
 for now. If the demand and need is felt in the future, it could be added then,
@@ -1145,7 +1169,7 @@
 containers. Containers such as vectors are obvious candidates for parallelisation,
 since it is easy to conceptually think of a vector as a being splittable into
 a number of smaller vectors, and then applying a divide and conquer approach to
-the vector subsets. However, even a sequentially accessed container such as a 
+the vector subsets. However, even a sequentially accessed container such as a
 linked list can be iterated in parallel, if cursors for each parallel executor
 can be obtained prior to execution of the loop. This typically involves iterating
 once through the container to obtain the cursors, but can still be benefit from
@@ -1161,9 +1185,10 @@
 
 Such loops would require manual chunking, where the user code explicitly calls
 the Split function of a Parallel iterator to obtain the Chunk_Array object that
-normally the implementation would request. This allows the user to express the 
+normally the implementation would request. This allows the user to express the
 parallelism more explicitly by writing an outer loop that iterates through the
-number of chunks and an inner loop that iterates through the elements of each chunk.
+number of chunks and an inner loop that iterates through the elements of each
+chunk.
 
 Since this capability exists for the containers, as all the containers have an
 Iterate primitive that return a parallel iterator object that can be used to
@@ -6531,6 +6556,309 @@
 
 ***************************************************************
 
+From: Brad Moore
+Sent: Saturday, December 30, 2018  1:34 PM
+
+I have been looking more closely at Tuckers paper from the Ada Users Journal on
+Container Iteration, and I think it would be worth incorporating some of those
+ideas.
+
+ http://www.ada-europe.org/archive/auj/auj-37-2.pdf  (scan to physical page 31,
+ logical page 95)
+
+In particular, providing a Split primitive on the Parallel_Iterator_Interface
+instead of a Jump function to Jump to an arbitrary cursor relative to another
+cursor, gives the container writer more flexibility in determining which cursors
+of the container should be used for the chunks, as well as possibly the number
+of chunks to be applied.
+
+This also provides a common, better defined interface that can be used by both
+the implementation, and the user. The compiler would use the interface under
+normal circumstances, but the user could also use the interface when manual
+chunking is needed, which would eliminate the need to provide a separate
+interface for that purpose.
+
+I think this can be accomplished with some fairly minor tweaks to the existing
+AI.
+
+As it stands, I would replace the addition to Ada.Iterator_Interfaces of;
+
+   use type Ada.Containers.Count_Type;
+   subtype Count_Type is Ada.Containers.Count_Type;
+
+   type Cursor_Offset is range -(Count_Type'Last - 1) .. Count_Type'Last - 1;
+
+   type Parallel_Iterator is limited interface and Forward_Iterator;
+
+   function Length
+     (Object   : Parallel_Iterator) return Count_Type is abstract;
+
+   function Jump
+     (Object   : Parallel_Iterator;
+      Position : Cursor;
+      Offset   : Cursor_Offset) return Cursor is abstract;
+
+
+with;
+
+   type Chunk_Array is limited interface;
+
+   function Length
+     (Object  : Chunk_Array) return Natural is abstract;
+
+   function Start
+     (Object : Chunk_Array;
+      Index  : Natural) return Cursor is abstract;
+
+   function Finish
+     (Object : Chunk_Array;
+      Index  : Natural) return Cursor is abstract;
+
+   type Parallel_Iterator is limited interface and Forward_Iterator;
+
+     function Split
+       (Object   : Parallel_Iterator) return Chunk_Array'Class is abstract;
+
+The Chunk_Array interface would provide the means to extract the cursors out of
+the Split result.
+
+The Length function indicates how many chunks were returned by the Split call,
+and Start, Finish return the start and end cursors for a particular chunk.
+
+Then for each of the standard containers, I would add a type definition for the
+Chunk_Array.
+
+For example, for Ada.Containers.Doubly_Linked_Lists, I would add;
+
+   type Chunk_Array (<>) is new
+     List_Iterator_Interfaces.Chunk_Array with private;
+
+I believe the Chunk_Array definition would be the only additional line needed in
+each container.
+
+Then, if a user wanted to manually chunk a list container, one could write
+something like;
+
+      Chunks : constant My_Lists.List_Iterator_Interfaces.Chunk_Array'Class :=
+          List.Iterate.Split;
+   begin
+
+      parallel
+      for Chunk in 1 .. Chunks.Length loop
+         Inner_Loop :
+         for Position in List.Iterate (Start => Chunks.Start(Chunk)) loop
+            ...
+            exit Inner_Loop when Position = Chunks.Finish (Chunk);
+         end loop Inner_Loop;
+      end loop;
+   end;
+
+Note that no additional syntax support is needed than is already proposed in the
+AI.
+
+Does this seem like an improvement?
+If so, I will update the AI to include these changes.
+
+***************************************************************
+
+From: Randy Brukardt
+Sent: Saturday, December 30, 2018  3:55 PM
+
+Tucker's idea certainly makes more sense than your old idea, which requires
+adding indexed access to containers that don't naturally have such access. But I
+would have expected the Split interface to at least take a requested number of
+chunks. Otherwise, the container has no way of knowing how many chunks would be
+optimal (since that depends on the number of tasklets available and other
+implementation details). It shouldn't be guessing. And it would seem that a
+sensible implementation of the interface you have would be to simply return a
+single chunk for every query, since that is easy to implement and makes as much
+sense as any other result. I think you'd want to prevent that somehow, and the
+best I can think of is to have a suggested number of chunks.
+
+Of course, it might make sense for the container to return some other number of
+chunks (if the container doesn't have enough elements for the requested number
+of chunks, for instance). So that part of the interface makes sense.
+
+But we definitely don't want the container interface to be tightly tied to the
+parallel loop implementation, which it would have to be if there is no number of
+chunks in the Split request. Hopefully both things can be implemented separately
+(quite possibly by different groups for larger compiler vendors).
+
+P.S. You might want to consider whether the routines of this interface ought to
+be declared nonblocking. One can't do that with the existing iterators because
+of compatibility, but you have no such concern.
+
+***************************************************************
+
+From: Brad Moore
+Sent: Sunday, December 31, 2018  3:05 PM
+
+> Tucker's idea certainly makes more sense than your old idea, which
+> requires adding indexed access to containers that don't naturally have such
+> access.
+
+I have actually modified Tuck's ideas from his paper in several ways, which I
+think are improvements.
+
+In particular, he had Parallel_Interfaces in a generic child package of
+Iterator_Interfaces, using a Cursor_Array formal as an incomplete type.
+
+I started off with that but couldn't get it to work, as the Cursor_Array had to
+be a private type, which then nobody, (Implementations or Users) could do
+anything with the private type. By defining the Chunk_Array interface in the
+same place as the iterator, I was able to eliminate the generic formal, allowing
+the interface definition to be moved into iterator_interfaces, which means only
+one instantiation is needed to get all iterator interfaces, which I think is
+more convenient.
+
+He also had the Cursor array being passed into Split as an out parameter. I
+think returning the Chunk_Array as a function result will be more convenient to
+users.
+
+Lastly, his Split operation was returning an array of cursors, whereas my Split
+returns an array of chunks where each chunk has a start and end cursor.
+
+I think this is safer, particularly for user usage, since with an array of
+cursors, the user has to be sure to not dereference the cursor representing the
+end of the chunk, because that is being used as the start of another chunk.
+Also, it eliminates the user having to deal with the end case for the last chunk
+where the last cursor would have been a No_Element cursor.
+
+With the current scheme, all cursors from first to last of a chunk are valid and
+non overlapping with other chunks. I think it also fits nicer for user usage,
+using the Iterate calls that accept a start parameter, where one can exit the
+inner loop by comparing to the last cursor of the chunk, as in my example from
+the previous email.
+
+> But I would have expected the Split interface to at least take a
+> requested number of chunks. Otherwise, the container has no way of
+> knowing how many chunks would be optimal (since that depends on the
+> number of tasklets available and other implementation details). It
+> shouldn't be guessing. And it would seem that a sensible
+> implementation of the interface you have would be to simply return a
+> single chunk for every query, since that is easy to implement and
+> makes as much sense as any other result. I think you'd want to prevent
+> that somehow, and the best I can think of is to have a suggested number of
+> chunks.
+
+I agree, I have prototyped a new version of Split that looks like;
+
+   function Split
+     (Object        : Parallel_Iterator;
+      Advised_Split : Natural)
+      return Chunk_Array'Class is abstract;
+
+Where Advised_Split is the recommended number of chunks passed in from the
+implementation, but can be ignored by the container writer if he/she so chooses.
+
+I also added another function to the Parallel_Iterator interface
+
+   function Iterations
+     (Object : Parallel_Iterator)
+      return Ada.Containers.Count_Type is abstract;
+
+Because I think the implementation will need to query the iterator to determine
+the number of iterations associated with the iterator so that the implementation
+can make a better informed decision about determining the number of chunks to
+suggest.
+
+I think for user chunking, the user often would prefer to not have to decide the
+number of chunks, so I was thinking of adding the following definitions to
+System.Multiprocessors.
+
+   type Iteration_Count is range -(2 **63) .. +(2 **63 - 1);
+   for Iteration_Count'Size use 64;
+
+   type Chunk_Count is range 0 .. 2 **32 - 1;
+
+   function Advised_Chunk_Count
+     (Iterations :  Iteration_Count) return Chunk_Count
+     witn Non_Blocking => False;
+
+Which provides a routine that the user can call to query the implementation for
+a recommended chunk count to use, given a number of iterations.
+
+I decided to make this routine Non_Blocking => False because the routine might
+want to query the processor load to see how many processors are idle.
+
+On Linux, I have found this can be done by reading system files from the /proc
+filesystem, but presumably that would be blocking behaviour.
+
+
+Lastly, I know we last thought another AI would be recommended, but now that
+container iterators can be defined this way, it makes it a lot simpler to define
+a package that can similarly support chunking for discrete type iteration.
+
+with Ada202x.Iterator_Interfaces;
+with Ada202x.Containers;
+
+generic
+   type Loop_Index is (<>);
+package Ada.Discrete_Chunking is
+
+   pragma Preelaborate;
+   pragma Remote_Types;
+
+   function Has_Element (Position : Loop_Index) return Boolean is (True);
+
+   package Chunk_Array_Iterator_Interfaces is new
+     Ada202x.Iterator_Interfaces (Loop_Index, Has_Element);
+
+   type Chunk_Array (<>) is new
+     Chunk_Array_Iterator_Interfaces.Chunk_Array with private;
+
+   function Iterate
+     (From : Loop_Index := Loop_Index'First;
+      To   : Loop_Index := Loop_Index'Last)
+   return Chunk_Array_Iterator_Interfaces.Parallel_Reversible_Iterator'Class;
+
+private
+   ...
+end Ada.Discrete_Chunking;
+
+This allows the user to write something like;
+
+   declare
+      package Manual_Chunking is new Ada.Discrete_Chunking (Natural);
+
+      Chunks : constant
+        Manual_Chunking.Chunk_Array_Iterator_Interfaces.Chunk_Array'Class :=
+          Manual_Chunking.Iterate.Split (Advised_Split => 10);
+   begin
+
+      parallel
+      for Chunk in 1 .. Chunks.Length loop
+         for I in Chunks.Start (Chunk) .. Chunks.Finish (Chunk) loop
+            ...
+         end loop;
+      end loop;
+   end;
+
+Which is very similar to the Container loop example.
+
+
+The only thing that would be nice to have with the Chunk_Array type returned by
+Split, is if it could be treated as a container so one could replace the loop
+above with;
+
+      parallel
+      for Chunk of Chunks loop
+         for I in Chunks.Start .. Chunks.Finish loop
+            ...
+         end loop;
+      end loop;
+
+But I suspect this is not currently possible to do, at least with something that
+returns Interface'Class because I think you'd need to apply the Iterator_Element
+aspect to the interface which cannot be done, since the interface doesn't know
+the Iterator_Element type. Maybe there is a way to work around this, but I think
+its probably good enough to require using "in" iterator loop syntax as above for
+these cases instead of "of" syntax. Other than manual chunking, it will be the
+implementation using the interface, so the "prettyness" of the syntax is not
+needed.
+
+***************************************************************
+
 From: Jeff Cousins
 Sent: Monday, January 1, 2018  6:15 PM
 
@@ -6669,5 +6997,364 @@
    also possible using containers.
 
 Happy New Year everyone!
+
+**************************************************************
+
+From: Tucker Taft
+Sent: Tuesday, January 2, 2018  9:35 AM
+
+> ...
+>
+> He also had the Cursor array being passed into Split as an out
+> parameter. I think returning the Chunk_Array as a function result will be more
+> convenient to users. ...
+
+Convenience to users seems somewhat irrelevant in a routine that is intended to
+be called by compiler-generated code.  Furthermore, the OUT parameter avoided
+the need for doing dynamic allocation and deallocation on a secondary stack,
+something which is painful in some environments, and not something you want to
+require every time you do something with a container.   Finally, the size of the
+passed-in array provided the specification of the number of chunks desired.
+
+***************************************************************
+
+From: Brad Moore
+Sent: Tuesday, January 2, 2018  10:36 AM
+
+> Convenience to users seems somewhat irrelevant in a routine that is
+> intended to be called by compiler-generated code.
+
+I agree that your original design made perfect sense for the original intent
+outlined in the paper, which was as something called only by compiler-generated
+code.
+
+I say the newer design has improvements in the context of now also allowing
+users to call the same routines, since there seems to be a number of cases where
+that would be needed. Since the user can now be involved, more thought is needed
+to making the interface more user-friendly.
+
+> Furthermore, the OUT parameter avoided
+> the need for doing dynamic allocation and deallocation on a secondary
+> stack, something which is painful in some environments, and not
+> something you want to require every time you do something with a container.
+
+Keep in mind that this occurs only for parallel usage, and for parallel usage
+for the parallelism to be worthwhile in the first place, I would think the
+amount of processing needed to do the allocation and deallocation of the chunk
+array would be insignificant compared to the amount of time needed to do the
+processing on the elements in the container. How much pain is there to do such
+allocations for such environments? I would think regardless how painful, it is
+still something that generally needs to be supported in such environments for
+other use cases.
+
+>  Finally, the size of
+> the passed-in array provided the specification of the number of chunks desired.
+
+Yes, except I thought the idea was also that the container implementor might
+want to override the number of desired chunks. As an out parameter, the
+container writer is more tied to the number passed in by the implementor. For a
+binary tree container for instance, maybe some power of two representing the top
+nodes in the tree, makes for a better division of work, and that might be less
+or more than the number of elements in the out parameter array. So long as the
+number of chunks is less than or equal to the number of elements in the
+container, it should work for parallel usage.
+
+***************************************************************
+
+From: Tucker Taft
+Sent: Tuesday, January 2, 2018  12:22 PM
+
+> I agree that your original design made perfect sense for the original
+> intent outlined in the paper, which was as something called only by
+> compiler-generated code.
+>
+> I say the newer design has improvements in the context of now also
+> allowing users to call the same routines, since there seems to be a number
+> of cases where that would be needed. Since the user can now be involved, more
+> thought is needed to making the interface more user-friendly.
+
+If that is really true, then I think we should consider making improvements on
+the syntactic sugar, rather than spending energy trying to make the
+compiler-oriented operations friendlier.
+
+>  Furthermore, the OUT parameter avoided
+>> the need for doing dynamic allocation and deallocation on a secondary
+>> stack, something which is painful in some environments, and not
+>> something you want to require every time you do something with a container.
+>
+> ...
+> How much pain is there to do such allocations for such environments? I
+> would think regardless how painful, it is still something that generally
+> needs to be supported in such environments for other use cases.
+
+I just don't think we want to insert this kind of unnecessary dynamic allocation
+inside of compiler-generated code.  We could provide a "user-friendly" version
+as well, though functions that return unconstrained arrays are not terribly
+friendly, in that you often have to call them as part of a declaration, which
+may require the insertion of yet another declare block in the middle of things.
+
+>   Finally, the size of
+>> the passed-in array provided the specification of the number of chunks desired.
+>
+> Yes, except I thought the idea was also that the container implementor
+> might want to override the number of desired chunks. As an out
+> parameter, the container writer is more tied to the number passed in
+> by the implementor. For a binary tree container for instance, maybe
+> some power of two representing the top nodes in the tree, makes for a better
+> division of work, and that might be less or more than the number of elements
+> in the out parameter array.
+
+I agree that some chunks at the end might end up empty, but producing more
+chunks than what the caller has specified as a "max" number of chunks seems
+undesirable.
+
+***************************************************************
+
+From: Randy Brukardt
+Sent: Wednesday, January 10, 2018  10:43 PM
+
+...
+> Since there are now quite a lot of changes being discussed compared to
+> the version of the AI that was sent out,
+>
+> I have attached a new version of the AI.
+
+Here's a list of editorial changes that I made to this version (there were
+enough so I posted this as a separate version, version /07):
+
+RM section/paragraph numbers don't include a space, and should not be prefixed
+by anything (in particular, by "RM"). AARM section/paragraph numbers should
+always be prefixed by "AARM". (This is part of the "Kiyoshi consistency rules",
+and as such is not negotiable).
+
+Only one space after a period ending a sentence. Text that Tuck wrote is almost
+always wrong about this, but don't copy that style!
+
+The rules for concurrent access includes a header and three bullets, and thus
+would best be described as "9.10(11-14)".
+
+The AI number of reduction expressions will be AI12-0242-1, so I plugged that
+in.
+
+The "rules for shared variables" are at a minimum 9.10(11-14); there is a
+specific change to 9.10(13) being recommended, so it seems best to mention both.
+"(see 9.10(11-14), and specifically 9.10(13))".
+
+The headers for wording are inconsistent or missing in various places, and the
+wording needs to be in paragraph order. Use either "Replace xx(xx)", "Modify
+xx(xx)", "Add after xx(xx)", or "Add new subclause xx". Normally, I'd end all of
+these with a colon (:) but there is some flexibility here as they're not
+mentioned in the "Kiyoshi rules". But we don't want them to vary for different
+paragraphs. One thing the "Kiyoshi" rules" does mention is that one never talks
+about "paragraphs", one just says "add after".
+
+Some specific issues:
+
+The grammar change at 5.5(3/3) has to be a "Replace" since there are no
+modification marks in the following text (and using those in grammar changes is
+always questionable, since [] and {} have a syntax meaning).
+
+There is no location at all specified for the Legality Rules. I added a header
+to insert them after 5.5(6/5). (That seems like the best place, since we want
+the basic definition of a "loop parameter" to occur before we start talking
+about the rules for such things.)
+
+The Legality Rules refer to specific paragraph numbers; that's not allowed in
+wording.
+
+In those rules: ... *parallel* reserve{d} word.
+
+A change at 5.5(7) has to go before a change at 5.5(9/4). (Jeff noted this.)
+
+"Modify [to] 5.5(9/4)" This section also has quote marks around the text for no
+known reason.
+
+The "with Ada.Containers" at 5.5.1(1/3) is not needed with the new
+specification, since it doesn't reference anything from that package. I deleted
+it.
+
+I added a separate header for the added paragraph after 5.5.2(10/3), and deleted
+the insertion marks (they're way too easy to miss). And there were no insertion
+marks for the new AARM note.
+
+Changed the header of 5.5.2(13/3) to: "Modify 5.5.2(13/3) [into three
+paragraphs]" because that's not obvious to a causal reader (me).
+
+"Section" is what we once might have called a chapter. These added things are
+subclauses.
+
+Some of the wording text has rather long lines. 80 character lines is generally
+the maximum. The "Iterate" paragraphs are especially bad.
+
+P.S. Brad, if you are going to make changes to this AI, please make sure you
+have version /07 first. If it isn't posted yet, please ask me for a copy.
+
+***************************************************************
+
+From: Randy Brukardt
+Sent: Wednesday, January 10, 2018  10:42 PM
+
+...
+> I have attached a new version of the AI.
+
+Here are my substantive comments on this AI. (See the other message for the
+editorial comments, all of which I've already applied.)
+
+> Legality Rules, added after 5.5(6/5):
+
+> A loop_statement with the *parallel* reserve word shall not update
+> variables global to the loop unless either the action is sequential
+> (see 9.10), or the expression for the update mentions the loop parameter.
+
+An action being "sequential" is a dynamic concept (actually, it is defined for
+"erroneous execution", but that is obviously a dynamic concept). We can't base
+Legality Rules on dynamic concepts, because they cut through privacy and the
+like (thus violating all of the good Ada principles).
+
+I thought the idea was to use Global to define this properly for a Legality
+Rule, essentially not allowing any call or other use of a global variable unless
+it is "synchronized" (using the meaning of that from Global). Exactly how to
+word this isn't obvious to me; perhaps there is some wording defining Global
+that could be reused. (The wording would also need to allow the exception you
+noted your wording above.)
+
+> In that same wording:
+
+> The sequence_of_statements of a loop_statement with the *parallel*
+> reserve word shall not consist of a statement that can invoke a
+> potentially blocking operation (see 9.5).
+
+Wrong. "Potentially blocking" is a dynamic concept (there shortly will be an AI
+on this mistake). You want to use the Legality Rules defined for Nonblocking
+(specifically, 9.5(58-65/5). Unfortunately, there is no term specifically for
+this (maybe there should have been). And Standard wording cannot use paragraph
+numbers. So perhaps say something like:
+
+The sequence_of_statements of a loop_statement with the *parallel* reserved word
+are considered to be contained in a nonblocking program unit for the purposes of
+Legality Rules (see 9.5).
+
+AARM Ramification: This meaning that calling subprograms that allow blocking, or
+directly blocking statements like an entry call, accept statement, or delay
+statement, are not allowed in the body of a parallel loop. This is true even if
+the surrounding unit allows blocking.
+
+> Add after 5.5(7):
+
+> When the reserved word parallel is present and a transfer of control
+> out of the loop occurs, an attempt is made to cancel further parallel
+> execution of the sequence_of_statements that has not yet started.
+
+I thought the intent was that we'd try to cancel further parallel execution of the sequence_of_statements that HAS started, and to prevent any further iterations from starting. In any case, we need to be more specific about what "cancel" means. (Is it "ab
ort", with all of the baggage of that? I'd hope not, but then precisely what is required to be canceled, and what *can* be canceled?)
+
+> Add after 5.5.2(10/3):
+
+> For a parallel generalized iterator, the operation Iterations of the
+> iterator type is called first to determine the number of iterations
+> associated with the iterator.
+
+I note in passing that this doesn't make any sense if we really add "when"
+filters, as the only way to know that actual number of iterations is to
+partially execute them (assuming the filter is an arbitrary expression). One
+probably would have to do chunking based on the number of iterations expected
+ignoring any filter, but that of course makes the filter essentially a lie (the
+iteration will have to happen regardless of the filter value; only the executed
+statements would change. Moreover, the chunking would often be suboptimal in
+such a case).
+
+> Modify 5.5.2(13/3) [into three paragraphs]
+
+The new third paragraph is:
+
+> If the loop parameter is a constant (see above), then the indexing
+> uses the default constant indexing function for the type of the
+> iterable container object for the loop; otherwise it uses the default variable
+> indexing function.
+
+The intent is that this applies to both forward/reverse container element
+iterators and parallel container element iterators (and no others), but as a
+separate paragraph following the parallel container element iterator this is not
+obvious. Probably it needs a lead-in like:
+
+For any kind of container element iterator, if the loop parameter is ...
+
+>New subclause 5.5.3 has:
+
+> generic
+>    type Loop_Index is (<>);
+> package Ada.Discrete_Chunking is
+>
+>    pragma Preelaborate;
+>    pragma Remote_Types;
+
+Use aspects, not pragmas, in new packages. (Otherwise, I'd have to complain that
+the unit name was not repeated as it is in all of the other language-defined
+packages.) So:
+
+generic
+   type Loop_Index is (<>);
+package Ada.Discrete_Chunking
+   with Preelaborate, Remote_Types is
+
+> New subclause 5.6.1.
+
+The Legality Rules here need reworking just like the ones in the loop cases.
+
+For some reason, the execution of a parallel block is described in a "Static
+Semantics" section. Put a "Dynamic Semantics" header in there somewhere!
+
+> Add after 11.5(20)
+>
+> Loop_Parameter_Check
+>  For a parallel loop, check that updates to a component of an array or
+>  to an  element of a container via the loop parameter are sequential. See
+>  9.10(11).
+
+This implies that there is a dynamic check somewhere. But there is no such check
+defined in 5.5 or anywhere else. (This is the pragma Suppress definition, but
+the actual check has to be defined, too, in particular as to what exception is
+raised. Look up any check in the RM index to see the appropriate form of the
+check wording.)
+
+> Add after D.16(5/3)
+>
+>   type Iteration_Count is range 0 .. implementation-defined;
+>   for Iteration_Count'Size use implementation-defined;
+>
+>   type Split_Count is range 0 .. implementation-defined;
+>
+>   function Advised_Split_Count
+>     (Iterations :  Iteration_Count) return Split_Count
+>       witn Non_Blocking => False;
+
+I don't see the point of the Iterations parameter here. An appropriate split
+would take an estimate as to how expensive the loop body (or block body, for
+that matter) is as well as the number of iterations. As such, it doesn't seem
+sensible to have such a function here (in package Multiprocessing). What seems
+appropriate here is a recommended number of executors; I'd suggest something
+like:
+
+   function Advised_Executors return CPU_Range
+       witn Non_Blocking => False;
+
+I used CPU_Range because it doesn't make much sense to have more executors than
+execution resources (processors). (Getting rid of the types simplifies this a
+lot.)
+
+Additionally, it might make sense to specify the task and/or CPU that is
+involved (as I can imagine the answer being different for different tasks). One
+hopes that you could call this for some other task as part of setup (and not
+just be restricted to querying this for yourself). However, since
+System.Multiprocessors seems to be designed to sit below the level of tasks (it
+has no task-based queries). So perhaps the more specific version belongs in
+Dispatching_Domains (along with Get_CPU).
+
+
+   function Advised_Executors (T   : Ada.Task_Identification.Task_Id :=
+                 Ada.Task_Identification.Current_Task) return CPU_Range
+       witn Non_Blocking => False;
+
+
+That's enough for tonight. :-)
 
 ***************************************************************

Questions? Ask the ACAA Technical Agent