dwww Home | Show directory contents | Find package


                                   Annex E
                                 (normative)

                             Distributed Systems


1   [This Annex defines facilities for supporting the implementation of
distributed systems using multiple partitions working cooperatively as part of
a single Ada program.]


                            Extensions to Ada 83

1.a         This Annex is new to Ada 95.


                           Post-Compilation Rules

2   A distributed system is an interconnection of one or more processing nodes
(a system resource that has both computational and storage capabilities), and
zero or more storage nodes (a system resource that has only storage
capabilities, with the storage addressable by one or more processing nodes).

3   A distributed program comprises one or more partitions that execute
independently (except when they communicate) in a distributed system.

4   The process of mapping the partitions of a program to the nodes in a
distributed system is called configuring the partitions of the program.


                         Implementation Requirements

5   The implementation shall provide means for explicitly assigning library
units to a partition and for the configuring and execution of a program
consisting of multiple partitions on a distributed system; the means are
implementation defined.

5.a         Implementation defined: The means for creating and executing
            distributed programs.


                         Implementation Permissions

6   An implementation may require that the set of processing nodes of a
distributed system be homogeneous.

        NOTES

7       1  The partitions comprising a program may be executed on differently
        configured distributed systems or on a nondistributed system without
        requiring recompilation. A distributed program may be partitioned
        differently from the same set of library units without recompilation.
        The resulting execution is semantically equivalent.

8       2  A distributed program retains the same type safety as the
        equivalent single partition program.


E.1 Partitions


1   [The partitions of a distributed program are classified as either active
or passive.]


                           Post-Compilation Rules

2   An active partition is a partition as defined in 10.2. A passive partition
is a partition that has no thread of control of its own, whose library units
are all preelaborated, and whose data and subprograms are accessible to one or
more active partitions.

2.a         Discussion: In most situations, a passive partition does not
            execute, and does not have a "real" environment task. Any
            execution involved in its elaboration and initialization occurs
            before it comes into existence in a distributed program (like most
            preelaborated entities). Likewise, there is no concrete meaning to
            passive partition termination.

3   A passive partition shall include only library_items that either are
declared pure or are shared passive (see 10.2.1 and E.2.1).

4   An active partition shall be configured on a processing node. A passive
partition shall be configured either on a storage node or on a processing node.

5   The configuration of the partitions of a program onto a distributed system
shall be consistent with the possibility for data references or calls between
the partitions implied by their semantic dependences. Any reference to data or
call of a subprogram across partitions is called a remote access.

5.a         Discussion: For example, an active partition that includes a unit
            with a semantic dependence on the declaration of another RCI
            package of some other active partition has to be connected to that
            other partition by some sort of a message passing mechanism.

5.b         A passive partition that is accessible to an active partition
            should have its storage addressable to the processor(s) of the
            active partition. The processor(s) should be able to read and
            write from/to that storage, as well as to perform "
            read-modify-write" operations (in order to support entry-less
            protected objects).


                              Dynamic Semantics

6   A library_item is elaborated as part of the elaboration of each partition
that includes it. If a normal library unit (see E.2) has state, then a
separate copy of the state exists in each active partition that elaborates it.
[The state evolves independently in each such partition.]

6.a         Ramification: Normal library units cannot be included in passive
            partitions.

7   [An active partition terminates when its environment task terminates.] A
partition becomes inaccessible if it terminates or if it is aborted. An active
partition is aborted when its environment task is aborted. In addition, if a
partition fails during its elaboration, it becomes inaccessible to other
partitions. Other implementation-defined events can also result in a partition
becoming inaccessible.

7.a         Implementation defined: Any events that can result in a partition
            becoming inaccessible.

8/1 For a prefix D that denotes a library-level declaration, excepting a
declaration of or within a declared-pure library unit, the following attribute
is defined:

9   D'Partition_Id
                Denotes a value of the type universal_integer that identifies
                the partition in which D was elaborated. If D denotes the
                declaration of a remote call interface library unit (see
                E.2.3) the given partition is the one where the body of D was
                elaborated.


                          Bounded (Run-Time) Errors

10/2 {AI95-00226-01} It is a bounded error for there to be cyclic elaboration
dependences between the active partitions of a single distributed program. The
possible effects, in each of the partitions involved, are deadlock during
elaboration, or the raising of Communication_Error or Program_Error.


                         Implementation Permissions

11  An implementation may allow multiple active or passive partitions to be
configured on a single processing node, and multiple passive partitions to be
configured on a single storage node. In these cases, the scheduling policies,
treatment of priorities, and management of shared resources between these
partitions are implementation defined.

11.a        Implementation defined: The scheduling policies, treatment of
            priorities, and management of shared resources between partitions
            in certain cases.

12  An implementation may allow separate copies of an active partition to be
configured on different processing nodes, and to provide appropriate
interactions between the copies to present a consistent state of the partition
to other active partitions.

12.a        Ramification: The language does not specify the nature of these
            interactions, nor the actual level of consistency preserved.

13  In an implementation, the partitions of a distributed program need not be
loaded and elaborated all at the same time; they may be loaded and elaborated
one at a time over an extended period of time. An implementation may provide
facilities to abort and reload a partition during the execution of a
distributed program.

14  An implementation may allow the state of some of the partitions of a
distributed program to persist while other partitions of the program terminate
and are later reinvoked.

        NOTES

15      3  Library units are grouped into partitions after compile time, but
        before run time. At compile time, only the relevant library unit
        properties are identified using categorization pragmas.

16      4  The value returned by the Partition_Id attribute can be used as a
        parameter to implementation-provided subprograms in order to query
        information about the partition.


                         Wording Changes from Ada 95

16.a/2      {AI95-00226-01} Corrected wording so that a partition that has an
            elaboration problem will either deadlock or raise an exception.
            While an Ada 95 implementation could allow some partitions to
            continue to execute, they could be accessing unelaborated data,
            which is very bad (and erroneous in a practical sense). Therefore,
            this isn't listed as an inconsistency.


E.2 Categorization of Library Units


1   [Library units can be categorized according to the role they play in a
distributed program. Certain restrictions are associated with each category to
ensure that the semantics of a distributed program remain close to the
semantics for a nondistributed program.]

2/3 {AI05-0243-1} A categorization pragma is a library unit pragma (see
10.1.5) that specifies a corresponding categorization aspect. A categorization
aspect restricts the declarations, child units, or semantic dependences of the
library unit to which it applies. A categorized library unit is a library unit
that has a categorization aspect that is True.

3/3 {AI05-0243-1} The pragmas Shared_Passive, Remote_Types, and
Remote_Call_Interface are categorization pragmas, and the associated aspects
are categorization aspects. In addition, for the purposes of this Annex, the
aspect Pure (see 10.2.1) is considered a categorization aspect and the pragma
Pure is considered a categorization pragma.

4/3 {8652/0078} {AI95-00048-01} {AI05-0243-1} [ A library package or generic
library package is called a shared passive library unit if the Shared_Passive
aspect of the unit is True. A library package or generic library package is
called a remote types library unit if the Remote_Types aspect of the unit is
True. A library unit is called a remote call interface if the
Remote_Call_Interface aspect of the unit is True.] A normal library unit is
one for which no categorization aspect is True.

4.a/3       Proof: {AI05-0243-1} {AI05-0299-1} These terms (other than "
            normal library unit") are really defined in the following
            subclauses.

4.a.1/1     Ramification: {8652/0078} {AI95-00048-01} A library subprogram can
            be a remote call interface, but it cannot be a remote types or
            shared passive library unit.

5/3 {AI05-0206-1} {AI05-0243-1} {AI05-0269-1} {AI05-0299-1} [The various
categories of library units and the associated restrictions are described in
this and the following subclauses. The categories are related hierarchically
in that the library units of one category can depend semantically only on
library units of that category or an earlier one in the hierarchy, except that
the body of a remote types or remote call interface library unit is
unrestricted, the declaration of a remote types or remote call interface
library unit may depend on preelaborated normal library units that are
mentioned only in private with clauses, and all categories can depend on
limited views.

6/3 {AI05-0243-1} {AI05-0269-1} The overall hierarchy (including declared
pure) is as follows, with a lower-numbered category being "earlier in the
hierarchy" in the sense of the previous paragraph:

6.1/3 1.
        Declared Pure

6.2/3 2.
        Shared Passive

6.3/3 3.
        Remote Types

6.4/3 4.
        Remote Call Interface

6.5/3 5.
        Normal (no restrictions)

Paragraphs 7 through 11 were deleted.

12  Declared pure and shared passive library units are preelaborated. The
declaration of a remote types or remote call interface library unit is
required to be preelaborable. ]

Paragraph 13 was deleted.


                         Implementation Permissions

14  Implementations are allowed to define other categorization pragmas.


                         Wording Changes from Ada 95

14.a/2      {8652/0078} {AI95-00048-01} Corrigendum: Clarified that a library
            subprogram can be a remote call interface unit.

14.b/2      {8652/0079} {AI95-00208-01} Corrigendum: Removed the requirement
            that types be represented the same in all partitions, because it
            prevents the definition of heterogeneous distributed systems and
            goes much further than required.


                        Wording Changes from Ada 2005

14.c/3      {AI05-0206-1} {AI05-0299-1} We now allow private withs of
            preelaborated units in Remote Types and Remote Call Interface
            units; this is documented as an extension in the subclauses where
            this is defined normatively.

14.d/3      {AI05-0243-1} {AI05-0299-1} We have introduced categorization
            aspects; these are documented as extensions in the subclauses
            where they actually are defined.


E.2.1 Shared Passive Library Units


1   [A shared passive library unit is used for managing global data shared
between active partitions. The restrictions on shared passive library units
prevent the data or tasks of one active partition from being accessible to
another active partition through references implicit in objects declared in
the shared passive library unit.]


                         Language Design Principles

1.a         The restrictions governing a shared passive library unit are
            designed to ensure that objects and subprograms declared in the
            package can be used safely from multiple active partitions, even
            though the active partitions live in different address spaces, and
            have separate run-time systems.


                                   Syntax

2       The form of a pragma Shared_Passive is as follows:

3         pragma Shared_Passive[(library_unit_name)];


                               Legality Rules

4/3 {AI05-0243-1} A pragma Shared_Passive is used to specify that a library
unit is a shared passive library unit, namely that the Shared_Passive aspect
of the library unit is True. The following restrictions apply to such a
library unit:

4.a/3       Aspect Description for Shared_Passive: A given package is used to
            represent shared memory in a distributed system.

5     * [it shall be preelaborable (see 10.2.1);]

5.a         Ramification: It cannot contain library-level declarations of
            protected objects with entries, nor of task objects. Task objects
            are disallowed because passive partitions don't have any threads
            of control of their own, nor any run-time system of their own.
            Protected objects with entries are disallowed because an entry
            queue contains references to calling tasks, and that would require
            in effect a pointer from a passive partition back to a task in
            some active partition.

6/3   * {AI05-0243-1} it shall depend semantically only upon declared pure or
        shared passive library_items;

6.a         Reason: Shared passive packages cannot depend semantically upon
            remote types packages because the values of an access type
            declared in a remote types package refer to the local heap of the
            active partition including the remote types package.

6.b/3       Ramification: {AI05-0243-1} We say library_item here, so that
            limited views are allowed; those are not library units, but they
            are library_item.

7/4   * {8652/0080} {AI95-00003-01} {AI12-0038-1} it shall not contain a
        library-level declaration of an access type that designates a
        class-wide type, nor a type with a part that is of a task type or
        protected type with entry_declarations;

7.a         Reason: These kinds of access types are disallowed because the
            object designated by an access value of such a type could contain
            an implicit reference back to the active partition on whose behalf
            the designated object was created.

7.1/4   * {AI12-0038-1} it shall not contain a library-level declaration that
        contains a name that denotes a type declared within a declared-pure
        package, if that type has a part that is of an access type; for the
        purposes of this rule, the parts considered include those of the full
        views of any private types or private extensions.

7.b/4       Reason: This rule breaks privacy by looking into the full views of
            private types. Avoiding privacy breakage here would have required
            disallowing the use in a shared passive package of any private
            type declared in a declared-pure package, which would have been
            severely incompatible.

8   Notwithstanding the definition of accessibility given in 3.10.2, the
declaration of a library unit P1 is not accessible from within the declarative
region of a shared passive library unit P2, unless the shared passive library
unit P2 depends semantically on P1.

8.a         Discussion: We considered a more complex rule, but dropped it.
            This is the simplest rule that recognizes that a shared passive
            package may outlive some other library package, unless it depends
            semantically on that package. In a nondistributed program, all
            library packages are presumed to have the same lifetime.

8.b         Implementations may define additional pragmas that force two
            library packages to be in the same partition, or to have the same
            lifetime, which would allow this rule to be relaxed in the
            presence of such pragmas.


                              Static Semantics

9   A shared passive library unit is preelaborated.


                           Post-Compilation Rules

10  A shared passive library unit shall be assigned to at most one partition
within a given program.

11  Notwithstanding the rule given in 10.2, a compilation unit in a given
partition does not need (in the sense of 10.2) the shared passive library
units on which it depends semantically to be included in that same partition;
they will typically reside in separate passive partitions.


                         Wording Changes from Ada 95

11.a/2      {8652/0080} {AI95-00003-01} Corrigendum: Corrected the wording to
            allow access types in blocks in shared passive generic packages.


                           Extensions to Ada 2005

11.b/3      {AI05-0243-1} Shared_Passive is now a categorization aspect, so it
            can be specified by an aspect_specification - although the pragma
            is still preferred by the Standard.


                       Incompatibilities With Ada 2012

11.c/4      {AI12-0038-1} Corrigendum: Uses of access types declared in
            declared-pure units are not allowed in library-level shared
            passive packages. These were allowed by Ada 2005 and Ada 2012, but
            it is unlikely that they work properly, as active partitions could
            disappear before the shared-passive partition. As such, the new
            errors are more likely to catch bugs than to cause them.


E.2.2 Remote Types Library Units


1   [A remote types library unit supports the definition of types intended for
use in communication between active partitions.]


                         Language Design Principles

1.a         The restrictions governing a remote types package are similar to
            those for a declared pure package. However, the restrictions are
            relaxed deliberately to allow such a package to contain
            declarations that violate the stateless property of pure packages,
            though it is presumed that any state-dependent properties are
            essentially invisible outside the package.


                                   Syntax

2       The form of a pragma Remote_Types is as follows:

3         pragma Remote_Types[(library_unit_name)];


                               Legality Rules

4/3 {AI05-0243-1} A pragma Remote_Types is used to specify that a library unit
is a remote types library unit, namely that the Remote_Types aspect of the
library unit is True. The following restrictions apply to the declaration of
such a library unit:

4.a/3       Aspect Description for Remote_Types: Types in a given package may
            be used in remote procedure calls.

5     * [it shall be preelaborable;]

6/3   * {AI05-0206-1} {AI05-0243-1} it shall depend semantically only on
        declared pure library_items, shared passive library units, other
        remote types library units, or preelaborated normal library units that
        are mentioned only in private with clauses;

6.a/3       Ramification: {AI05-0243-1} We say declared pure library_item
            here, so that (all) limited views are allowed; those are not
            library units, but they are declared pure library_items.

7     * it shall not contain the declaration of any variable within the
        visible part of the library unit;

7.a         Reason: This is essentially a "methodological" restriction. A
            separate copy of a remote types package is included in each
            partition that references it, just like a normal package.
            Nevertheless, a remote types package is thought of as an "
            essentially pure" package for defining types to be used for
            interpartition communication, and it could be misleading to
            declare visible objects when no remote data access is actually
            being provided.

8/2   * {AI95-00240-01} {AI95-00366-01} the full view of each type declared in
        the visible part of the library unit that has any available stream
        attributes shall support external streaming (see 13.13.2).

8.a         Reason: This is to prevent the use of the predefined Read and
            Write attributes of an access type as part of the Read and Write
            attributes of a visible type.

8.b/2       Ramification: {AI95-00366-01} Types that do not have available
            stream attributes are excluded from this rule; that means that
            attributes do not need to be specified for most limited types. It
            is only necessary to specify attributes for nonlimited types that
            have a part that is of any access type, and for extensions of
            limited types with available stream attributes where the
            record_extension_part includes a subcomponent of an access type,
            where the access type does not have specified attributes.

9/3 {8652/0082} {AI95-00164-01} {AI05-0060-1} A named access type declared in
the visible part of a remote types or remote call interface library unit is
called a remote access type. Such a type shall be:

9.1/1   * {8652/0082} {AI95-00164-01} an access-to-subprogram type, or

9.2/3   * {8652/0082} {AI95-00164-01} {AI05-0060-1} a general access type that
        designates a class-wide limited private type, a class-wide limited
        interface type, or a class-wide private extension all of whose
        ancestors are either private extensions, limited interface types, or
        limited private types.

9.3/1 {8652/0081} {AI95-00004-01} A type that is derived from a remote access
type is also a remote access type.

10  The following restrictions apply to the use of a remote
access-to-subprogram type:

11/2   * {AI95-00431-01} A value of a remote access-to-subprogram type shall
        be converted only to or from another (subtype-conformant) remote
        access-to-subprogram type;

12    * The prefix of an Access attribute_reference that yields a value of a
        remote access-to-subprogram type shall statically denote a
        (subtype-conformant) remote subprogram.

13  The following restrictions apply to the use of a remote
access-to-class-wide type:

14/3   * {8652/0083} {AI95-00047-01} {AI95-00240-01} {AI95-00366-01}
        {AI05-0060-1} {AI05-0101-1} The primitive subprograms of the
        corresponding specific type shall only have access parameters if they
        are controlling formal parameters. The primitive functions of the
        corresponding specific type shall only have an access result if it is
        a controlling access result. Each noncontrolling formal parameter and
        noncontrolling result type shall support external streaming (see
        13.13.2);

14.1/3   * {AI05-0060-1} {AI05-0215-1} {AI05-0269-1} The corresponding
        specific type shall not have a primitive procedure with the
        Synchronization aspect specified unless the synchronization_kind is
        Optional (see 9.5);

15    * A value of a remote access-to-class-wide type shall be explicitly
        converted only to another remote access-to-class-wide type;

16/4   * {AI12-0034-1} A value of a remote access-to-class-wide type shall be
        dereferenced (or implicitly converted to an anonymous access type)
        only as part of a dispatching call to a primitive operation of the
        designated type where the value designates a controlling operand of
        the call (see E.4, "Remote Subprogram Calls");

16.a/4      Ramification: {AI12-0034-1} Stream attributes of the designated
            type are not primitive operations of the designated type, and thus
            remote calls to them are prohibited by this rule. This is good, as
            the access parameter of a stream attribute does not have external
            streaming, and thus cannot be a parameter of a remote call.

16.1/3   * {AI05-0101-1} A controlling access result value for a primitive
        function with any controlling operands of the corresponding specific
        type shall either be explicitly converted to a remote
        access-to-class-wide type or be part of a dispatching call where the
        value designates a controlling operand of the call;

17/4   * {AI95-00366-01} {AI12-0085-1} The Storage_Pool attribute is not
        defined for a remote access-to-class-wide type; the expected type for
        an allocator shall not be a remote access-to-class-wide type. A remote
        access-to-class-wide type shall not be an actual parameter for a
        generic formal access type. The Storage_Size attribute of a remote
        access-to-class-wide type yields 0. The Storage_Pool and Storage_Size
        aspects shall not be specified for a remote access-to-class-wide type.

17.a/3      Reason: {AI05-0005-1} All of these restrictions are because there
            is no storage pool associated with a remote access-to-class-wide
            type. The Storage_Size is defined to be 0 so that there is no
            conflict with the rules for pure units.

17.b/4      Ramification: {AI12-0085-1} The prohibition against specifying the
            Storage_Size aspect for an access-to-class-wide type applies to
            any method of doing that, including via either a
            aspect_specification or an attribute_definition_clause.


                             Erroneous Execution

17.1/4 {AI12-0076-1} Execution is erroneous if some operation (other than the
initialization or finalization of the object) modifies the value of a constant
object declared in the visible part of a remote types package.

17.c/4      Discussion: This could be accomplished via a self-referencing
            pointer or via squirrelling a writable pointer to a controlled
            object.

        NOTES

18      5  A remote types library unit need not be pure, and the types it
        defines may include levels of indirection implemented by using access
        types. User-specified Read and Write attributes (see 13.13.2) provide
        for sending values of such a type between active partitions, with
        Write marshalling the representation, and Read unmarshalling any
        levels of indirection.

19/3    6  {AI05-0060-1} The value of a remote access-to-class-wide limited
        interface can designate an object of a nonlimited type derived from
        the interface.

20/3    7  {AI05-0060-1} A remote access type may designate a class-wide
        synchronized, protected, or task interface type.

20.a/3      Proof: Synchronized, protected, and task interfaces are all
            considered limited interfaces, see 3.9.4.


                        Incompatibilities With Ada 95

20.b/3      {AI95-00240-01} {AI05-0248-1} Amendment Correction: The wording
            was changed from "user-specified" to "available" read and write
            attributes. (This was then further changed, see below.) This means
            that an access type with the attributes specified in the private
            part would originally have been sufficient to allow the access
            type to be used in a remote type, but that is no longer allowed.
            Similarly, the attributes of a remote type that has access
            components have to be specified in the visible part. These changes
            were made so that the rules were consistent with the rules
            introduced for the Corrigendum for stream attributes; moreover,
            legality should not depend on the contents of the private part.


                            Extensions to Ada 95

20.c/3      {AI95-00366-01} {AI05-0005-1} Remote types that cannot be streamed
            (that is, have no available stream attributes) do not require the
            specification of stream attributes. This is necessary so that most
            extensions of Limited_Controlled do not need stream attributes
            defined (otherwise there would be a significant incompatibility,
            as Limited_Controlled would need stream attributes, and then all
            extensions of it also would need stream attributes).


                         Wording Changes from Ada 95

20.d/2      {8652/0081} {AI95-00004-01} Corrigendum: Added missing wording so
            that a type derived from a remote access type is also a remote
            access type.

20.e/2      {8652/0083} {AI95-00047-01} Corrigendum: Clarified that
            user-defined Read and Write attributes are required for the
            primitive subprograms corresponding to a remote
            access-to-class-wide type.

20.f/2      {8652/0082} {AI95-00164-01} Corrigendum: Added missing wording so
            that a remote access type can designate an appropriate private
            extension.

20.g/2      {AI95-00366-01} Changed the wording to use the newly defined term
            type that supports external streaming, so that various issues with
            access types in pure units and implicitly declared attributes for
            type extensions are properly handled.

20.h/2      {AI95-00366-01} Defined Storage_Size to be 0 for remote
            access-to-class-wide types, rather than having it undefined. This
            eliminates issues with pure units requiring a defined storage size.

20.i/2      {AI95-00431-01} Corrected the wording so that a value of a local
            access-to-subprogram type cannot be converted to a remote
            access-to-subprogram type, as intended (and required by the
            ACATS).


                       Incompatibilities With Ada 2005

20.j/4      {AI05-0101-1} {AI12-0005-1} Correction: Added rules for returning
            of remote access-to-class-wide types; this had been missed in the
            past. While programs that returned unstreamable types from RCI
            functions were legal, it is not clear what they could have done
            (as the results could not be marshalled). Similarly, RCI functions
            that return remote controlling access types could try to save
            those values, but it is unlikely that a compiler would know how to
            do that usefully. Thus, it seems unlikely that any real programs
            will be impacted by these changes.


                           Extensions to Ada 2005

20.k/3      {AI05-0060-1} Correction: Clarified that anonymous access types
            are never remote access types (and can be used in remote types
            units subject to the normal restrictions). Added wording to allow
            limited class-wide interfaces to be designated by remote access
            types.

20.l/3      {AI05-0206-1} Added wording to allow private withs of
            preelaborated normal units in the specification of a remote types
            unit.

20.m/3      {AI05-0243-1} Remote_Types is now a categorization aspect, so it
            can be specified by an aspect_specification - although the pragma
            is still preferred by the Standard.


                        Wording Changes from Ada 2012

20.n/4      {AI12-0034-1} Corrigendum: Clarified that dispatching remote
            stream attribute calls are prohibited. We don't document this as
            an incompatibility, as the stream parameter cannot be marshalled
            for a remote call (it doesn't have external streaming), so it's
            impossible that any working program depends on this functionality.

20.o/4      {AI12-0076-1} Corrigendum: Explicitly stated that modifying a
            visible constant in a remote types package is erroneous. We don't
            document this as inconsistent as implementations certainly can
            still do whatever they were previously doing (no change is
            required); moreover, this case (and many more) were erroneous in
            Ada 2005 and before, so we're just restoring the previous
            semantics.

20.p/4      {AI12-0085-1} Corrigendum: Clarified that specifying the
            Storage_Pool or Storage_Size aspect for an access-to-class-wide
            type is not allowed. The intent is clear, and no implementation
            has ever allowed specifying the aspects (the attributes already
            cannot be specified), so we don't document this as an
            incompatibility.


E.2.3 Remote Call Interface Library Units


1   [A remote call interface library unit can be used as an interface for
remote procedure calls (RPCs) (or remote function calls) between active
partitions.]


                         Language Design Principles

1.a         The restrictions governing a remote call interface library unit
            are intended to ensure that the values of the actual parameters in
            a remote call can be meaningfully sent between two active
            partitions.


                                   Syntax

2       The form of a pragma Remote_Call_Interface is as follows:

3         pragma Remote_Call_Interface[(library_unit_name)];

4       The form of a pragma All_Calls_Remote is as follows:

5         pragma All_Calls_Remote[(library_unit_name)];

6       A pragma All_Calls_Remote is a library unit pragma.


                               Legality Rules

7/3 {8652/0078} {AI95-00048-01} {AI05-0243-1} A pragma Remote_Call_Interface
is used to specify that a library unit is a remote call interface (RCI),
namely that the Remote_Call_Interface aspect of the library unit is True. A
subprogram declared in the visible part of such a library unit, or declared by
such a library unit, is called a remote subprogram.

7.a/3       Aspect Description for Remote_Call_Interface: Subprograms in a
            given package may be used in remote procedure calls.

8/3 {AI05-0206-1} {AI05-0243-1} The declaration of an RCI library unit shall
be preelaborable (see 10.2.1), and shall depend semantically only upon
declared pure library_items, shared passive library units, remote types
library units, other remote call interface library units, or preelaborated
normal library units that are mentioned only in private with clauses.

8.a/3       Ramification: {AI05-0243-1} We say declared pure library_item
            here, so that (all) limited views are allowed; those are not
            library units, but they are declared pure library_items.

9/1 {8652/0078} {AI95-00048-01} In addition, the following restrictions apply
to an RCI library unit:

10/1   * {8652/0078} {AI95-00048-01} its visible part shall not contain the
        declaration of a variable;

10.a/1      Reason: {8652/0078} {AI95-00048-01} Remote call interface units do
            not provide remote data access. A shared passive package has to be
            used for that.

11/1   * {8652/0078} {AI95-00048-01} its visible part shall not contain the
        declaration of a limited type;

11.a/2      Reason: {AI95-00240-01} {AI95-00366-01} We disallow the
            declaration of task and protected types, since calling an entry or
            a protected subprogram implicitly passes an object of a limited
            type (the target task or protected object). We disallow other
            limited types since we require that such types have available Read
            and Write attributes, but we certainly don't want the Read and
            Write attributes themselves to involve remote calls (thereby
            defeating their purpose of marshalling the value for remote
            calls).

12/1   * {8652/0078} {AI95-00048-01} its visible part shall not contain a
        nested generic_declaration;

12.a        Reason: This is disallowed because the body of the nested generic
            would presumably have access to data inside the body of the RCI
            package, and if instantiated in a different partition, remote data
            access might result, which is not supported.

13/3   * {8652/0078} {AI95-00048-01} {AI05-0229-1} it shall not be, nor shall
        its visible part contain, the declaration of a subprogram for which
        aspect Inline is True;

14/3   * {8652/0078} {AI95-00048-01} {AI95-00240-01} {AI95-00366-01}
        {AI05-0101-1} it shall not be, nor shall its visible part contain, a
        subprogram (or access-to-subprogram) declaration whose profile has a
        parameter or result of a type that does not support external streaming
        (see 13.13.2);

14.a/3      Ramification: {AI05-0101-1} No anonymous access types support
            external streaming, so they are never allowed as parameters or
            results of RCI subprograms.

15    * any public child of the library unit shall be a remote call interface
        library unit.

15.a        Reason: No restrictions apply to the private part of an RCI
            package, and since a public child can "see" the private part of
            its parent, such a child must itself have a Remote_Call_Interface
            pragma, and be assigned to the same partition (see below).

15.b        Discussion: We considered making the public child of an RCI
            package implicitly RCI, but it seemed better to require an
            explicit pragma to avoid any confusion.

15.c        Note that there is no need for a private child to be an RCI
            package, since it can only be seen from the body of its parent or
            its siblings, all of which are required to be in the same active
            partition.

16/3 {AI05-0229-1} A pragma All_Calls_Remote sets the All_Calls_Remote
representation aspect of the library unit to which the pragma applies to the
value True. If the All_Calls_Remote aspect of a library unit is True, the
library unit shall be a remote call interface.

16.a/4      Aspect Description for All_Calls_Remote: All indirect or
            dispatching remote subprogram calls and all direct remote
            subprogram calls should use the Partition Communication Subsystem.


                           Post-Compilation Rules

17  A remote call interface library unit shall be assigned to at most one
partition of a given program. A remote call interface library unit whose
parent is also an RCI library unit shall be assigned only to the same
partition as its parent.

17.a/1      Implementation Note: {8652/0078} {AI95-00048-01} The declaration
            of an RCI unit, with a calling-stub body, is automatically
            included in all active partitions with compilation units that
            depend on it. However the whole RCI library unit, including its
            (non-stub) body, will only be in one of the active partitions.

18  Notwithstanding the rule given in 10.2, a compilation unit in a given
partition that semantically depends on the declaration of an RCI library unit,
needs (in the sense of 10.2) only the declaration of the RCI library unit, not
the body, to be included in that same partition. [Therefore, the body of an
RCI library unit is included only in the partition to which the RCI library
unit is explicitly assigned.]


                         Implementation Requirements

19/4 {8652/0078} {AI95-00048-01} {AI05-0229-1} {AI12-0031-1} If aspect
All_Calls_Remote is True for a given RCI library unit, then the implementation
shall route any of the following calls through the Partition Communication
Subsystem (PCS); see E.5:

19.1/4   * {AI12-0031-1} A direct call to a subprogram of the RCI unit from
        outside the declarative region of the unit;

19.2/4   * {AI12-0031-1} An indirect call through a remote
        access-to-subprogram value that designates a subprogram of the RCI
        unit;

19.3/4   * {AI12-0031-1} A dispatching call with a controlling operand
        designated by a remote access-to-class-wide value whose tag identifies
        a type declared in the RCI unit.

19.a/4      Discussion: {8652/0078} {AI95-00048-01} {AI05-0229-1}
            {AI12-0031-1} When this aspect is False (or not used), it is
            presumed that most implementations will not make calls through the
            PCS if the call originates in the same partition as that of the
            RCI unit. When this aspect is True, all indirect or dispatching
            remote subprogram calls to the RCI unit and all direct calls from
            outside the subsystem rooted at the RCI unit are treated like
            calls from outside the partition, ensuring that the PCS is
            involved in all such calls (for debugging, redundancy, etc.).

19.b/4      Reason: {AI12-0031-1} There is no point to force local direct
            calls (including calls from children) to go through the PCS, since
            on the target system these calls are always local, and all the
            units are in the same active partition.


                         Implementation Permissions

20/3 {AI05-0243-1} An implementation need not support the
Remote_Call_Interface pragma or aspect nor the All_Calls_Remote pragma.
[Explicit message-based communication between active partitions can be
supported as an alternative to RPC.]

20.a        Ramification: Of course, it is pointless to support the
            All_Calls_Remote pragma if the Remote_Call_Interface pragma (or
            some approximate equivalent) is not supported.


                        Incompatibilities With Ada 95

20.b/3      {AI95-00240-01} {AI05-0248-1} Amendment Correction: The wording
            was changed from "user-specified" to "available" read and write
            attributes. (This was then further changed, see below.) This means
            that a type with the attributes specified in the private part
            would originally have been allowed as a formal parameter of an RCI
            subprogram, but that is no longer allowed. This change was made so
            that the rules were consistent with the rules introduced for the
            Corrigendum for stream attributes; moreover, legality should not
            depend on the contents of the private part.


                         Wording Changes from Ada 95

20.c/2      {8652/0078} {AI95-00048-01} Corrigendum: Changed the wording to
            allow a library subprogram to be a remote call interface unit.

20.d/2      {AI95-00366-01} Changed the wording to use the newly defined term
            type that supports external streaming, so that various issues with
            access types in pure units and implicitly declared attributes for
            type extensions are properly handled.


                       Incompatibilities With Ada 2005

20.e/3      {AI05-0101-1} Correction: Added a rule to ensure that function
            results are streamable; this was missing in previous versions of
            Ada. While programs that returned unstreamable types from RCI
            functions were legal, it is not clear what they could have done
            (as the results could not be marshalled). Thus, it seems unlikely
            that any real programs will be impacted by this change.


                           Extensions to Ada 2005

20.f/3      {AI05-0206-1} Added wording to allow private withs of
            preelaborated normal units in the specification of a remote call
            interface unit.

20.g/3      {AI05-0229-1} All_Calls_Remote is now a representation aspect, so
            it can be specified by an aspect_specification - although the
            pragma is still preferred by the Standard.

20.h/3      {AI05-0243-1} Remote_Call_Interface is now a categorization
            aspect, so it can be specified by an aspect_specification -
            although the pragma is still preferred by the Standard.


                        Inconsistencies With Ada 2012

20.i/4      {AI12-0031-1} Corrigendum: Redefined when indirect and dispatching
            remote calls have to be remote for a unit for which the aspect
            All_Calls_Remote is True. With the new rules, a local target
            called indirectly or via dispatching will be routed through the
            PCS, while that was not necessarily true in earlier Ada. If a
            program depended on local targets not being routed through the PCS
            even when All_Calls_Remote is used, then it might behave
            differently or fail in corrected Ada 2012. This is highly unlikely
            as PCS is going to be able to communicate with any partition of
            the program, including the local partition.


E.3 Consistency of a Distributed System


1/3 {AI05-0299-1} [This subclause defines attributes and rules associated with
verifying the consistency of a distributed program.]


                         Language Design Principles

1.a/3       {AI05-0248-1} The rules guarantee that remote call interface and
            shared passive library units are consistent among all partitions
            prior to the execution of a distributed program, so that the
            semantics of the distributed program are well defined.


                              Static Semantics

2/1 For a prefix P that statically denotes a program unit, the following
attributes are defined:

3   P'Version   Yields a value of the predefined type String that identifies
                the version of the compilation unit that contains the
                declaration of the program unit.

4   P'Body_Version
                Yields a value of the predefined type String that identifies
                the version of the compilation unit that contains the body
                (but not any subunits) of the program unit.

5/1 {8652/0084} {AI95-00104-01} The version of a compilation unit changes
whenever the compilation unit changes in a semantically significant way. This
International Standard does not define the exact meaning of "semantically
significant". It is unspecified whether there are other events (such as
recompilation) that result in the version of a compilation unit changing.

5.a/1       This paragraph was deleted.

5.1/1 {8652/0084} {AI95-00104-01} If P is not a library unit, and P has no
completion, then P'Body_Version returns the Body_Version of the innermost
program unit enclosing the declaration of P. If P is a library unit, and P has
no completion, then P'Body_Version returns a value that is different from
Body_Version of any version of P that has a completion.


                          Bounded (Run-Time) Errors

6   In a distributed program, a library unit is consistent if the same version
of its declaration is used throughout. It is a bounded error to elaborate a
partition of a distributed program that contains a compilation unit that
depends on a different version of the declaration of a shared passive or RCI
library unit than that included in the partition to which the shared passive
or RCI library unit was assigned. As a result of this error, Program_Error can
be raised in one or both partitions during elaboration; in any case, the
partitions become inaccessible to one another.

6.a         Ramification: Because a version changes if anything on which it
            depends undergoes a version change, requiring consistency for
            shared passive and remote call interface library units is
            sufficient to ensure consistency for the declared pure and remote
            types library units that define the types used for the objects and
            parameters through which interpartition communication takes place.

6.b         Note that we do not require matching Body_Versions; it is
            irrelevant for shared passive and remote call interface packages,
            since only one copy of their body exists in a distributed program
            (in the absence of implicit replication), and we allow the bodies
            to differ for declared pure and remote types packages from
            partition to partition, presuming that the differences are due to
            required error corrections that took place during the execution of
            a long-running distributed program. The Body_Version attribute
            provides a means for performing stricter consistency checks.


                         Wording Changes from Ada 95

6.c/2       {8652/0084} {AI95-00104-01} Corrigendum: Clarified the meaning of
            'Version and 'Body_Version.


E.4 Remote Subprogram Calls


1   A remote subprogram call is a subprogram call that invokes the execution
of a subprogram in another partition. The partition that originates the remote
subprogram call is the calling partition, and the partition that executes the
corresponding subprogram body is the called partition. Some remote procedure
calls are allowed to return prior to the completion of subprogram execution.
These are called asynchronous remote procedure calls.

2   There are three different ways of performing a remote subprogram call:

3     * As a direct call on a (remote) subprogram explicitly declared in a
        remote call interface;

4     * As an indirect call through a value of a remote access-to-subprogram
        type;

5     * As a dispatching call with a controlling operand designated by a value
        of a remote access-to-class-wide type.

6   The first way of calling corresponds to a static binding between the
calling and the called partition. The latter two ways correspond to a dynamic
binding between the calling and the called partition.

7/3 {AI05-0101-1} Remote types library units (see E.2.2) and remote call
interface library units (see E.2.3) define the remote subprograms or remote
access types used for remote subprogram calls.


                         Language Design Principles

7.a         Remote subprogram calls are standardized since the RPC paradigm is
            widely-used, and establishing an interface to it in the annex will
            increase the portability and reusability of distributed programs.


                               Legality Rules

8   In a dispatching call with two or more controlling operands, if one
controlling operand is designated by a value of a remote access-to-class-wide
type, then all shall be.


                              Dynamic Semantics

9   For the execution of a remote subprogram call, subprogram parameters (and
later the results, if any) are passed using a stream-oriented representation
(see 13.13.1) [which is suitable for transmission between partitions]. This
action is called marshalling. Unmarshalling is the reverse action of
reconstructing the parameters or results from the stream-oriented
representation. [Marshalling is performed initially as part of the remote
subprogram call in the calling partition; unmarshalling is done in the called
partition. After the remote subprogram completes, marshalling is performed in
the called partition, and finally unmarshalling is done in the calling
partition.]

10  A calling stub is the sequence of code that replaces the subprogram body
of a remotely called subprogram in the calling partition. A receiving stub is
the sequence of code (the "wrapper") that receives a remote subprogram call on
the called partition and invokes the appropriate subprogram body.

10.a        Discussion: The use of the term stub in this annex should not be
            confused with body_stub as defined in 10.1.3. The term stub is
            used here because it is a commonly understood term when talking
            about the RPC paradigm.

11  Remote subprogram calls are executed at most once, that is, if the
subprogram call returns normally, then the called subprogram's body was
executed exactly once.

12  The task executing a remote subprogram call blocks until the subprogram in
the called partition returns, unless the call is asynchronous. For an
asynchronous remote procedure call, the calling task can become ready before
the procedure in the called partition returns.

13  If a construct containing a remote call is aborted, the remote subprogram
call is cancelled. Whether the execution of the remote subprogram is
immediately aborted as a result of the cancellation is implementation defined.

13.a        Implementation defined: Whether the execution of the remote
            subprogram is immediately aborted as a result of cancellation.

14  If a remote subprogram call is received by a called partition before the
partition has completed its elaboration, the call is kept pending until the
called partition completes its elaboration (unless the call is cancelled by
the calling partition prior to that).

15  If an exception is propagated by a remotely called subprogram, and the
call is not an asynchronous call, the corresponding exception is reraised at
the point of the remote subprogram call. For an asynchronous call, if the
remote procedure call returns prior to the completion of the remotely called
subprogram, any exception is lost.

16  The exception Communication_Error (see E.5) is raised if a remote call
cannot be completed due to difficulties in communicating with the called
partition.

17  All forms of remote subprogram calls are potentially blocking operations
(see 9.5.1).

17.a        Reason: Asynchronous remote procedure calls are potentially
            blocking since the implementation may require waiting for the
            availability of shared resources to initiate the remote call.

18/1 {8652/0085} {AI95-00215-01} In a remote subprogram call with a formal
parameter of a class-wide type, a check is made that the tag of the actual
parameter identifies a tagged type declared in a declared-pure or shared
passive library unit, or in the visible part of a remote types or remote call
interface library unit. Program_Error is raised if this check fails. In a
remote function call which returns a class-wide type, the same check is made
on the function result.

18.a/1      Discussion: {8652/0085} {AI95-00215-01} This check makes certain
            that the specific type passed or returned in an RPC satisfies the
            rules for a "communicable" type. Normally this is guaranteed by
            the compile-time restrictions on remote call interfaces. However,
            with class-wide types, it is possible to pass an object whose tag
            identifies a type declared outside the "safe" packages.

18.b        This is considered an accessibility_check since only the types
            declared in "safe" packages are considered truly "global"
            (cross-partition). Other types are local to a single partition.
            This is analogous to the "accessibility" of global vs. local
            declarations in a single-partition program.

18.c        This rule replaces a rule from an early version of Ada 9X which
            was given in the subclause on Remote Types Library Units (now
            E.2.2, "Remote Types Library Units"). That rule tried to prevent
            "bad" types from being sent by arranging for their tags to
            mismatch between partitions. However, that interfered with other
            uses of tags. The new rule allows tags to agree in all partitions,
            even for those types which are not "safe" to pass in an RPC.

19  In a dispatching call with two or more controlling operands that are
designated by values of a remote access-to-class-wide type, a check is made
[(in addition to the normal Tag_Check - see 11.5)] that all the remote
access-to-class-wide values originated from Access attribute_references that
were evaluated by tasks of the same active partition. Constraint_Error is
raised if this check fails.

19.a        Implementation Note: When a remote access-to-class-wide value is
            created by an Access attribute_reference, the identity of the
            active partition that evaluated the attribute_reference should be
            recorded in the representation of the remote access value.


                         Implementation Requirements

20  The implementation of remote subprogram calls shall conform to the PCS
interface as defined by the specification of the language-defined package
System.RPC (see E.5). The calling stub shall use the Do_RPC procedure unless
the remote procedure call is asynchronous in which case Do_APC shall be used.
On the receiving side, the corresponding receiving stub shall be invoked by
the RPC-receiver.

20.a        Implementation Note: One possible implementation model is as
            follows:

20.b        The code for calls to subprograms declared in an RCI package is
            generated normally, that is, the call-site is the same as for a
            local subprogram call. The code for the remotely callable
            subprogram bodies is also generated normally. Subprogram's
            prologue and epilogue are the same as for a local call.

20.c        When compiling the specification of an RCI package, the compiler
            generates calling stubs for each visible subprogram. Similarly,
            when compiling the body of an RCI package, the compiler generates
            receiving stubs for each visible subprogram together with the
            appropriate tables to allow the RPC-receiver to locate the correct
            receiving stub.

20.d        For the statically bound remote calls, the identity of the remote
            partition is statically determined (it is resolved at
            configuration/link time).

20.e        The calling stub operates as follows:

20.f          * It allocates (or reuses) a stream of Params_Stream_Type of
                Initial_Size, and initializes it by repeatedly calling Write
                operations, first to identify which remote subprogram in the
                receiving partition is being called, and then to pass the
                incoming value of each of the in and in out parameters of the
                call.

20.g/3        * {AI05-0229-1} It allocates (or reuses) a stream for the
                Result, unless an aspect Asynchronous is specified as True for
                the procedure.

20.h/3        * {AI05-0229-1} It calls Do_RPC unless an aspect Asynchronous is
                specified as True for the procedure in which case it calls
                Do_APC. An access value designating the message stream
                allocated and initialized above is passed as the Params
                parameter. An access value designating the Result stream is
                passed as the Result parameter.

20.i/3        * {AI05-0229-1} If the aspect Asynchronous is not specified for
                the procedure, Do_RPC blocks until a reply message arrives,
                and then returns to the calling stub. The stub returns after
                extracting from the Result stream, using Read operations, the
                in out and out parameters or the function result. If the reply
                message indicates that the execution of the remote subprogram
                propagated an exception, the exception is propagated from
                Do_RPC to the calling stub, and thence to the point of the
                original remote subprogram call. If Do_RPC detects that
                communication with the remote partition has failed, it
                propagates Communication_Error.

20.j        On the receiving side, the RPC-receiver procedure operates as
            follows:

20.k          * It is called from the PCS when a remote-subprogram-call
                message is received. The call originates in some remote call
                receiver task executed and managed in the context of the PCS.

20.l          * It extracts information from the stream to identify the
                appropriate receiving stub.

20.m          * The receiving stub extracts the in and in out parameters using
                Read from the stream designated by the Params parameter.

20.n          * The receiving stub calls the actual subprogram body and, upon
                completion of the subprogram, uses Write to insert the results
                into the stream pointed to by the Result parameter. The
                receiving stub returns to the RPC-receiver procedure which in
                turn returns to the PCS. If the actual subprogram body
                propagates an exception, it is propagated by the RPC-receiver
                to the PCS, which handles the exception, and indicates in the
                reply message that the execution of the subprogram body
                propagated an exception. The exception occurrence can be
                represented in the reply message using the Write attribute of
                Ada.Exceptions.Exception_Occurrence.

20.o        For remote access-to-subprogram types:

20.p        A value of a remote access-to-subprogram type can be represented
            by the following components: a reference to the remote partition,
            an index to the package containing the remote subprogram, and an
            index to the subprogram within the package. The values of these
            components are determined at run time when the remote access value
            is created. These three components serve the same purpose when
            calling Do_APC/RPC, as in the statically bound remote calls; the
            only difference is that they are evaluated dynamically.

20.q        For remote access-to-class-wide types:

20.r        For each remote access-to-class-wide type, a calling stub is
            generated for each dispatching operation of the designated type.
            In addition, receiving stubs are generated to perform the remote
            dispatching operations in the called partition. The appropriate
            subprogram_body is determined as for a local dispatching call once
            the receiving stub has been reached.

20.s        A value of a remote access-to-class-wide type can be represented
            with the following components: a reference to the remote
            partition, an index to a table (created one per each such access
            type) containing addresses of all the dispatching operations of
            the designated type, and an access value designating the actual
            remote object.

20.t        Alternatively, a remote access-to-class-wide value can be
            represented as a normal access value, pointing to a "stub" object
            which in turn contains the information mentioned above. A call on
            any dispatching operation of such a stub object does the remote
            call, if necessary, using the information in the stub object to
            locate the target partition, etc. This approach has the advantage
            that less special-casing is required in the compiler. All access
            values can remain just a simple address.

20.u        For a call to Do_RPC or Do_APC: The partition ID of all
            controlling operands are checked for equality (a Constraint_Error
            is raised if this check fails). The partition ID value is used for
            the Partition parameter. An index into the tagged-type-descriptor
            is created. This index points to the receiving stub of the
            class-wide operation. This index and the index to the table
            (described above) are written to the stream. Then, the actual
            parameters are marshalled into the message stream. For a
            controlling operand, only the access value designating the remote
            object is required (the other two components are already present
            in the other parameters).

20.v        On the called partition (after the RPC-receiver has transferred
            control to the appropriate receiving stub) the parameters are
            first unmarshalled. Then, the tags of the controlling operands
            (obtained by dereferencing the pointer to the object) are checked
            for equality. If the check fails Constraint_Error is raised and
            propagated back to the calling partition, unless it is a result of
            an asynchronous call. Finally, a dispatching call to the specific
            subprogram (based on the controlling object's tag) is made. Note
            that since this subprogram is not in an RCI package, no specific
            stub is generated for it, it is called normally from the
            dispatching stub.

20.1/1 {8652/0086} {AI95-00159-01} With respect to shared variables in shared
passive library units, the execution of the corresponding subprogram body of a
synchronous remote procedure call is considered to be part of the execution of
the calling task. The execution of the corresponding subprogram body of an
asynchronous remote procedure call proceeds in parallel with the calling task
and does not signal the next action of the calling task (see 9.10).

        NOTES

21      8  A given active partition can both make and receive remote
        subprogram calls. Thus, an active partition can act as both a client
        and a server.

22      9  If a given exception is propagated by a remote subprogram call, but
        the exception does not exist in the calling partition, the exception
        can be handled by an others choice or be propagated to and handled by
        a third partition.

22.a        Discussion: This situation can happen in a case of dynamically
            nested remote subprogram calls, where an intermediate call
            executes in a partition that does not include the library unit
            that defines the exception.


                         Wording Changes from Ada 95

22.b/2      {8652/0086} {AI95-00159-01} Corrigendum: Added rules so that tasks
            can safely access shared passive objects.

22.c/2      {8652/0085} {AI95-00215-01} Corrigendum: Clarified that the check
            on class-wide types also applies to values returned from remote
            subprogram call functions.


                        Wording Changes from Ada 2005

22.d/3      {AI05-0101-1} Correction: Corrected the text to note that remote
            access types can be defined in remote types units.


E.4.1 Asynchronous Remote Calls


1/3 {AI05-0229-1} [This subclause introduces the aspect Asynchronous which can
be specified to allow a remote subprogram call to return prior to completion
of the execution of the corresponding remote subprogram body.]

Paragraphs 2 through 7 were deleted.


                              Static Semantics

8/3 {AI05-0229-1} For a remote procedure, the following language-defined
representation aspect may be specified:

8.1/3 Asynchronous
                The type of aspect Asynchronous is Boolean. If directly
                specified, the aspect_definition shall be a static expression.
                If not specified, the aspect is False.

8.a/3       Aspect Description for Asynchronous: Remote procedure calls are
            asynchronous; the caller continues without waiting for the call to
            return.

8.2/3 {AI05-0229-1} For a remote access type, the following language-defined
representation aspect may be specified:

8.3/3 Asynchronous
                The type of aspect Asynchronous is Boolean. If directly
                specified, the aspect_definition shall be a static expression.
                If not specified (including by inheritance), the aspect is
                False.


                               Legality Rules

8.4/3 {AI05-0229-1} If aspect Asynchronous is specified for a remote
procedure, the formal parameters of the procedure shall all be of mode in.

8.5/3 {AI05-0229-1} If aspect Asynchronous is specified for a remote access
type, the type shall be a remote access-to-class-wide type, or the type shall
be a remote access-to-procedure type with the formal parameters of the
designated profile of the type all of mode in.


                              Dynamic Semantics

9/3 {AI05-0229-1} A remote call is asynchronous if it is a call to a
procedure, or a call through a value of an access-to-procedure type, for which
aspect Asynchronous is True. In addition, if aspect Asynchronous is True for a
remote access-to-class-wide type, then a dispatching call on a procedure with
a controlling operand designated by a value of the type is asynchronous if the
formal parameters of the procedure are all of mode in.


                         Implementation Requirements

10  Asynchronous remote procedure calls shall be implemented such that the
corresponding body executes at most once as a result of the call.

10.a        To be honest: It is not clear that this rule can be tested or even
            defined formally.


                           Extensions to Ada 2005

10.b/3      {AI05-0229-1} Aspect Asynchronous is new; pragma Asynchronous is
            now obsolescent.


E.4.2 Example of Use of a Remote Access-to-Class-Wide Type



                                  Examples

1   Example of using a remote access-to-class-wide type to achieve dynamic
binding across active partitions:

2       package Tapes is
           pragma Pure(Tapes);
           type Tape is abstract tagged limited private;
           -- Primitive dispatching operations where
           -- Tape is controlling operand
           procedure Copy (From, To : access Tape; Num_Recs : in Natural) is abstract;
           procedure Rewind (T : access Tape) is abstract;
           -- More operations
        private
           type Tape is ...
        end Tapes;

3       with Tapes;
        package Name_Server is
           pragma Remote_Call_Interface;
           -- Dynamic binding to remote operations is achieved
           -- using the access-to-limited-class-wide type Tape_Ptr
           type Tape_Ptr is access all Tapes.Tape'Class;
           -- The following statically bound remote operations
           -- allow for a name-server capability in this example
           function  Find     (Name : String) return Tape_Ptr;
           procedure Register (Name : in String; T : in Tape_Ptr);
           procedure Remove   (T : in Tape_Ptr);
           -- More operations
        end Name_Server;

4       package Tape_Driver is
          -- Declarations are not shown, they are irrelevant here
        end Tape_Driver;

5       with Tapes, Name_Server;
        package body Tape_Driver is
           type New_Tape is new Tapes.Tape with ...
           procedure Copy
            (From, To : access New_Tape; Num_Recs: in Natural) is
           begin
             . . .
           end Copy;
           procedure Rewind (T : access New_Tape) is
           begin
              . . .
           end Rewind;
           -- Objects remotely accessible through use
           -- of Name_Server operations
           Tape1, Tape2 : aliased New_Tape;
        begin
           Name_Server.Register ("NINE-TRACK",  Tape1'Access);
           Name_Server.Register ("SEVEN-TRACK", Tape2'Access);
        end Tape_Driver;

6       with Tapes, Name_Server;
        -- Tape_Driver is not needed and thus not mentioned in the with_clause
        procedure Tape_Client is
           T1, T2 : Name_Server.Tape_Ptr;
        begin
           T1 := Name_Server.Find ("NINE-TRACK");
           T2 := Name_Server.Find ("SEVEN-TRACK");
           Tapes.Rewind (T1);
           Tapes.Rewind (T2);
           Tapes.Copy (T1, T2, 3);
        end Tape_Client;

7   Notes on the example:

7.a         Discussion: The example does not show the case where tapes are
            removed from or added to the system. In the former case, an
            appropriate exception needs to be defined to instruct the client
            to use another tape. In the latter, the Name_Server should have a
            query function visible to the clients to inform them about the
            availability of the tapes in the system.

8/1 This paragraph was deleted.

9     * The package Tapes provides the necessary declarations of the type and
        its primitive operations.

10    * Name_Server is a remote call interface package and is elaborated in a
        separate active partition to provide the necessary naming services
        (such as Register and Find) to the entire distributed program through
        remote subprogram calls.

11    * Tape_Driver is a normal package that is elaborated in a partition
        configured on the processing node that is connected to the tape
        device(s). The abstract operations are overridden to support the
        locally declared tape devices (Tape1, Tape2). The package is not
        visible to its clients, but it exports the tape devices (as remote
        objects) through the services of the Name_Server. This allows for tape
        devices to be dynamically added, removed or replaced without requiring
        the modification of the clients' code.

12    * The Tape_Client procedure references only declarations in the Tapes
        and Name_Server packages. Before using a tape for the first time, it
        needs to query the Name_Server for a system-wide identity for that
        tape. From then on, it can use that identity to access the tape device.

13    * Values of remote access type Tape_Ptr include the necessary
        information to complete the remote dispatching operations that result
        from dereferencing the controlling operands T1 and T2.


E.5 Partition Communication Subsystem


1/2 {AI95-00273-01} [The Partition Communication Subsystem (PCS) provides
facilities for supporting communication between the active partitions of a
distributed program. The package System.RPC is a language-defined interface to
the PCS.]

1.a         Reason: The prefix RPC is used rather than RSC because the term
            remote procedure call and its acronym are more familiar.


                              Static Semantics

2   The following language-defined library package exists:

3       with Ada.Streams; -- see 13.13.1
        package System.RPC is

4          type Partition_Id is range 0 .. implementation-defined;

5          Communication_Error : exception;

6          type Params_Stream_Type (
              Initial_Size : Ada.Streams.Stream_Element_Count) is new
              Ada.Streams.Root_Stream_Type with private;

7          procedure Read(
              Stream : in out Params_Stream_Type;
              Item : out Ada.Streams.Stream_Element_Array;
              Last : out Ada.Streams.Stream_Element_Offset);

8          procedure Write(
              Stream : in out Params_Stream_Type;
              Item : in Ada.Streams.Stream_Element_Array);

9          -- Synchronous call
           procedure Do_RPC(
              Partition  : in Partition_Id;
              Params     : access Params_Stream_Type;
              Result     : access Params_Stream_Type);

10         -- Asynchronous call
           procedure Do_APC(
              Partition  : in Partition_Id;
              Params     : access Params_Stream_Type);

11         -- The handler for incoming RPCs
           type RPC_Receiver is access procedure(
              Params     : access Params_Stream_Type;
              Result     : access Params_Stream_Type);

12         procedure Establish_RPC_Receiver(
              Partition : in Partition_Id;
              Receiver  : in RPC_Receiver);

13      private
           ... -- not specified by the language
        end System.RPC;

14  A value of the type Partition_Id is used to identify a partition.

14.a/2      Implementation defined: The range of type System.RPC.Partition_Id.

15  An object of the type Params_Stream_Type is used for identifying the
particular remote subprogram that is being called, as well as marshalling and
unmarshalling the parameters or result of a remote subprogram call, as part of
sending them between partitions.

16  [The Read and Write procedures override the corresponding abstract
operations for the type Params_Stream_Type.]


                              Dynamic Semantics

17  The Do_RPC and Do_APC procedures send a message to the active partition
identified by the Partition parameter.

17.a        Implementation Note: It is assumed that the RPC interface is above
            the message-passing layer of the network protocol stack and is
            implemented in terms of it.

18  After sending the message, Do_RPC blocks the calling task until a reply
message comes back from the called partition or some error is detected by the
underlying communication system in which case Communication_Error is raised at
the point of the call to Do_RPC.

18.a        Reason: Only one exception is defined in System.RPC, although many
            sources of errors might exist. This is so because it is not always
            possible to distinguish among these errors. In particular, it is
            often impossible to tell the difference between a failing
            communication link and a failing processing node. Additional
            information might be associated with a particular
            Exception_Occurrence for a Communication_Error.

19  Do_APC operates in the same way as Do_RPC except that it is allowed to
return immediately after sending the message.

20  Upon normal return, the stream designated by the Result parameter of
Do_RPC contains the reply message.

21  The procedure System.RPC.Establish_RPC_Receiver is called once,
immediately after elaborating the library units of an active partition (that
is, right after the elaboration of the partition) if the partition includes an
RCI library unit, but prior to invoking the main subprogram, if any. The
Partition parameter is the Partition_Id of the active partition being
elaborated. The Receiver parameter designates an implementation-provided
procedure called the RPC-receiver which will handle all RPCs received by the
partition from the PCS. Establish_RPC_Receiver saves a reference to the
RPC-receiver; when a message is received at the called partition, the
RPC-receiver is called with the Params stream containing the message. When the
RPC-receiver returns, the contents of the stream designated by Result is
placed in a message and sent back to the calling partition.

21.a        Implementation Note: It is defined by the PCS implementation
            whether one or more threads of control should be available to
            process incoming messages and to wait for their completion.

21.b        Implementation Note: At link-time, the linker provides the
            RPC-receiver and the necessary tables to support it. A call on
            Establish_RPC_Receiver is inserted just before the call on the
            main subprogram.

21.c        Reason: The interface between the PCS (the System.RPC package) and
            the RPC-receiver is defined to be dynamic in order to allow the
            elaboration sequence to notify the PCS that all packages have been
            elaborated and that it is safe to call the receiving stubs. It is
            not guaranteed that the PCS units will be the last to be
            elaborated, so some other indication that elaboration is complete
            is needed.

22  If a call on Do_RPC is aborted, a cancellation message is sent to the
called partition, to request that the execution of the remotely called
subprogram be aborted.

22.a        To be honest: The full effects of this message are dependent on
            the implementation of the PCS.

23  The subprograms declared in System.RPC are potentially blocking
operations.


                         Implementation Requirements

24  The implementation of the RPC-receiver shall be reentrant[, thereby
allowing concurrent calls on it from the PCS to service concurrent remote
subprogram calls into the partition].

24.a        Reason: There seems no reason to allow the implementation of
            RPC-receiver to be nonreentrant, even though we don't require that
            every implementation of the PCS actually perform concurrent calls
            on the RPC-receiver.

24.1/1 {8652/0087} {AI95-00082-01} An implementation shall not restrict the
replacement of the body of System.RPC. An implementation shall not restrict
children of System.RPC. [The related implementation permissions in the
introduction to Annex A do not apply.]

24.a.1/1    Reason: The point of System.RPC is to let the user tailor the
            communications mechanism without requiring changes to or other
            cooperation from the compiler. However, implementations can
            restrict the replacement of language-defined units. This
            requirement overrides that permission for System.RPC.

24.2/1 {8652/0087} {AI95-00082-01} If the implementation of System.RPC is
provided by the user, an implementation shall support remote subprogram calls
as specified.

24.b/2      Discussion: {AI95-00273-01} If the implementation takes advantage
            of the implementation permission to use a different specification
            for System.RPC, it still needs to use it for remote subprogram
            calls, and allow the user to replace the body of System.RPC. It
            just isn't guaranteed to be portable to do so in Ada 2005 - an
            advantage which was more theoretical than real anyway.


                         Documentation Requirements

25  The implementation of the PCS shall document whether the RPC-receiver is
invoked from concurrent tasks. If there is an upper limit on the number of
such tasks, this limit shall be documented as well, together with the
mechanisms to configure it (if this is supported).

25.a/2      This paragraph was deleted.

25.a.1/2    Documentation Requirement: Whether the RPC-receiver is invoked
            from concurrent tasks, and if so, the number of such tasks.


                         Implementation Permissions

26  The PCS is allowed to contain implementation-defined interfaces for
explicit message passing, broadcasting, etc. Similarly, it is allowed to
provide additional interfaces to query the state of some remote partition
(given its partition ID) or of the PCS itself, to set timeouts and retry
parameters, to get more detailed error status, etc. These additional
interfaces should be provided in child packages of System.RPC.

26.a        Implementation defined: Implementation-defined interfaces in the
            PCS.

27  A body for the package System.RPC need not be supplied by the
implementation.

27.a        Reason: It is presumed that a body for the package System.RPC
            might be extremely environment specific. Therefore, we do not
            require that a body be provided by the (compiler) implementation.
            The user will have to write a body, or acquire one, appropriate
            for the target environment.

27.1/3 {AI95-00273-01} {AI05-0299-1} An alternative declaration is allowed for
package System.RPC as long as it provides a set of operations that is
substantially equivalent to the specification defined in this subclause.

27.b/2      Reason: Experience has proved that the definition of System.RPC
            given here is inadequate for interfacing to existing distribution
            mechanisms (such as CORBA), especially on heterogeneous systems.
            Rather than mandate a change in the mechanism (which would break
            existing systems), require implementations to support multiple
            mechanisms (which is impractical), or prevent the use of Annex E
            facilities with existing systems (which would be silly), we simply
            make this facility optional.

27.c/2      One of the purposes behind System.RPC was that knowledgeable
            users, rather than compiler vendors, could create this package
            tailored to their networks. Experience has shown that users get
            their RPC from vendors anyway; users have not taken advantage of
            the flexibility provided by this defined interface. Moreover, one
            could compare this defined interface to requiring Ada compilers to
            use a defined interface to implement tasking. No one thinks that
            the latter is a good idea, why should anyone believe that the
            former is?

27.d/3      {AI05-0299-1} Therefore, this subclause is made optional. We
            considered deleting the subclause outright, but we still require
            that users may replace the package (whatever its interface). Also,
            it still provides a useful guide to the implementation of this
            feature.


                            Implementation Advice

28  Whenever possible, the PCS on the called partition should allow for
multiple tasks to call the RPC-receiver with different messages and should
allow them to block until the corresponding subprogram body returns.

28.a/2      Implementation Advice: The PCS should allow for multiple tasks to
            call the RPC-receiver.

29  The Write operation on a stream of type Params_Stream_Type should raise
Storage_Error if it runs out of space trying to write the Item into the
stream.

29.a.1/2    Implementation Advice: The System.RPC.Write operation should raise
            Storage_Error if it runs out of space when writing an item.

29.a        Implementation Note: An implementation could also dynamically
            allocate more space as needed, only propagating Storage_Error if
            the allocator it calls raises Storage_Error. This storage could be
            managed through a controlled component of the stream object, to
            ensure that it is reclaimed when the stream object is finalized.

        NOTES

30      10  The package System.RPC is not designed for direct calls by user
        programs. It is instead designed for use in the implementation of
        remote subprograms calls, being called by the calling stubs generated
        for a remote call interface library unit to initiate a remote call,
        and in turn calling back to an RPC-receiver that dispatches to the
        receiving stubs generated for the body of a remote call interface, to
        handle a remote call received from elsewhere.


                        Incompatibilities With Ada 95

30.a/2      {AI95-00273-01} The specification of System.RPC can now be
            tailored for an implementation. If a program replaces the body of
            System.RPC with a user-defined body, it might not compile in a
            given implementation of Ada 2005 (if the specification of
            System.RPC has been changed).


                         Wording Changes from Ada 95

30.b/2      {8652/0087} {AI95-00082-01} Corrigendum: Clarified that the user
            can replace System.RPC.

Generated by dwww version 1.15 on Thu May 23 12:42:26 CEST 2024.