Contents Index Previous Next
10.2 Program Execution
1
{program} {program
execution} {running a
program: See program execution} An Ada
program consists of a set of
partitions[, which can execute
in parallel with one another, possibly in a separate address space, and
possibly on a separate computer.]
Post-Compilation Rules
2
{partition [distributed]}
{partition building}
A partition is a program or part of a program that
can be invoked from outside the Ada implementation. [For example, on
many systems, a partition might be an executable file generated by the
system linker.]
{explicitly assign} The
user can
explicitly assign library units to a partition. The assignment
is done in an implementation-defined manner. The compilation units included
in a partition are those of the explicitly assigned library units, as
well as other compilation units
needed by those library units.
The compilation units needed by a given compilation unit are determined
as follows (unless specified otherwise via an implementation-defined
pragma, or by some other implementation-defined
means):
{linking: See partition building}
{compilation units needed (by a
compilation unit) [distributed]} {needed
(of a compilation unit by another) [distributed]}
2.a
Discussion: From a run-time point
of view, an Ada 95 partition is identical to an Ada 83 program -- implementations
were always allowed to provide inter-program communication mechanisms. The additional
semantics of partitions is that interfaces between them can be defined to obey
normal language rules (as is done in Annex E, ``Distributed
Systems''), whereas interfaces between separate programs had no particular
semantics.
2.b
Implementation defined: The
manner of explicitly assigning library units to a partition.
2.c
Implementation defined: The
implementation-defined means, if any, of specifying which compilation
units are needed by a given compilation unit.
2.d
Discussion: There are no pragmas
that ``specify otherwise'' defined by the core language. However, an implementation
is allowed to provide such pragmas, and in fact Annex E,
``Distributed Systems'' defines some pragmas whose semantics
includes reducing the set of compilation units described here.
3
- A compilation unit needs itself;
4
- If a compilation unit is needed, then so are any compilation
units upon which it depends semantically;
5
- If a library_unit_declaration
is needed, then so is any corresponding library_unit_body;
6
- If a compilation unit with stubs is needed, then so are
any corresponding subunits.
6.a
Discussion: Note that in
the environment, the stubs are replaced with the corresponding proper_bodies.
6.b
Discussion: Note that a
child unit is not included just because its parent is included -- to
include a child, mention it in a with_clause.
7
{main subprogram (for a partition)}
The user can optionally designate (in an implementation-defined
manner) one subprogram as the
main subprogram for the partition.
A main subprogram, if specified, shall be a subprogram.
7.a
Discussion: This may seem
superfluous, since it follows from the definition. But we would like
to have every error message that might be generated (before run time)
by an implementation correspond to some explicitly stated ``shall'' rule.
7.b
Of course, this does not mean
that the ``shall'' rules correspond one-to-one with an implementation's
error messages. For example, the rule that says overload resolution ``shall''
succeed in producing a single interpretation would correspond to many
error messages in a good implementation -- the implementation would want
to explain to the user exactly why overload resolution failed. This is
especially true for the syntax rules -- they are considered part of overload
resolution, but in most cases, one would expect an error message based
on the particular syntax rule that was violated.
7.c
Implementation defined: The
manner of designating the main subprogram of a partition.
7.d
Ramification: An implementation
cannot require the user to specify, say, all of the library units to
be included. It has to support, for example, perhaps the most typical
case, where the user specifies just one library unit, the main program.
The implementation has to do the work of tracking down all the other
ones.
8
{environment task}
Each partition has an anonymous
environment task[,
which is an implicit outermost task whose execution elaborates the
library_items
of the environment
declarative_part,
and then calls the main subprogram, if there is one. A partition's execution
is that of its tasks.]
8.a
Ramification: An environment
task has no master; all nonenvironment tasks have masters.
8.b
An implementation is allowed to
support multiple concurrent executions of the same partition.
9
[The order of elaboration of library units is
determined primarily by the
elaboration dependences.]
{elaboration
dependence (library_item on another)} {dependence
(elaboration)} There is an elaboration
dependence of a given
library_item
upon another if the given
library_item
or any of its subunits depends semantically on the other
library_item.
In addition, if a given
library_item
or any of its subunits has a
pragma
Elaborate or Elaborate_All that mentions another library unit, then there
is an elaboration dependence of the given
library_item
upon the body of the other library unit, and, for Elaborate_All only,
upon each
library_item needed by
the declaration of the other library unit.
9.a.1/1
Discussion: {8652/0107}
``Mentions'' is used informally in the above rule; it is not intended to
refer to the definition of mentions in 10.1.2.
It would have been better to use ``named'' instead of ``mentioned'' above.
9.a
See above for a definition of
which library_items are ``needed
by'' a given declaration.
9.b
Note that elaboration dependences
are among library_items, whereas
the other two forms of dependence are among compilation units. Note that
elaboration dependence includes semantic dependence. It's a little bit
sad that pragma Elaborate_Body can't be folded into this mechanism. It
follows from the definition that the elaboration dependence relationship
is transitive. Note that the wording of the rule does not need to take
into account a semantic dependence of a library_item
or one of its subunits upon a subunit of a different library unit, because
that can never happen.
10
The environment
task for a partition has the following structure:
11
task Environment_Task;
12
task body Environment_Task is
... (1) -- The environment declarative_part
-- (that is, the sequence of library_items) goes here.
begin
... (2) -- Call the main subprogram, if there is one.
end Environment_Task;
12.a
Ramification: The name
of the environment task is written in italics here to indicate that this
task is anonymous.
12.b
Discussion: The model is different
for a ``passive partition'' (see E.1). Either there
is no environment task, or its sequence_of_statements
is an infinite loop rather than a call on a main subprogram.
13
{environment
declarative_part (for the environment task of a partition) [partial]}
The environment
declarative_part
at (1) is a sequence of
declarative_items
consisting of copies of the
library_items
included in the partition. [The order of elaboration of
library_items
is the order in which they appear in the environment
declarative_part]:
14
- The order of all included library_items
is such that there are no forward elaboration dependences.
14.a
Ramification: This rule
is written so that if a library_item
depends on itself, we don't require it to be elaborated before itself.
See AI83-00113/12. This can happen only in pathological circumstances.
For example, if a library subprogram_body
has no corresponding subprogram_declaration,
and one of the subunits of the subprogram_body
mentions the subprogram_body in
a with_clause, the subprogram_body
will depend on itself. For another example, if a library_unit_body
applies a pragma Elaborate_All to
its own declaration, then the library_unit_body
will depend on itself.
15
- Any included library_unit_declaration
to which a pragma Elaborate_Body
applies is immediately followed by its library_unit_body,
if included.
15.a
Discussion: This implies
that the body of such a library unit shall not ``with'' any of its own
children, or anything else that depends semantically upon the declaration
of the library unit.
16
- All library_items
declared pure occur before any that are not declared pure.
17
- All preelaborated library_items
occur before any that are not preelaborated.
17.a
Discussion: Normally, if two partitions
contain the same compilation unit, they each contain a separate copy
of that compilation unit. See Annex E, ``Distributed
Systems'' for cases where two partitions share the same copy of something.
17.b
There is no requirement that the
main subprogram be elaborated last. In fact, it is possible to write
a partition in which the main subprogram cannot be elaborated last.
17.c
Ramification: This declarative_part
has the properties required of all environments (see 10.1.4).
However, the environment declarative_part
of a partition will typically contain fewer compilation units than the environment
declarative_part used at compile time --
only the ``needed'' ones are included in the partition.
18
There shall be a total order of the library_items
that obeys the above rules. The order is otherwise implementation defined.
18.a
Discussion: The only way
to violate this rule is to have Elaborate, Elaborate_All, or Elaborate_Body
pragmas that cause circular ordering
requirements, thus preventing an order that has no forward elaboration
dependences.
18.b
Implementation defined: The
order of elaboration of library_items.
18.c
To be honest: {requires
a completion (library_unit_declaration) [partial]} {notwithstanding}
Notwithstanding what the RM95 says elsewhere, each
rule that requires a declaration to have a corresponding completion is
considered to be a Post-Compilation Rule when the declaration is that
of a library unit.
18.d
Discussion: Such rules
may be checked at ``link time,'' for example. Rules requiring the completion
to have certain properties, on the other hand, are checked at compile
time of the completion.
19
The full expanded names of the library units
and subunits included in a given partition shall be distinct.
19.a
Reason: This is a Post-Compilation
Rule because making it a Legality Rule would violate the Language Design
Principle labeled ``legality determinable via semantic dependences.''
20
The sequence_of_statements
of the environment task (see (2) above) consists of either:
21
- A call to the main subprogram, if the partition has one.
If the main subprogram has parameters, they are passed; where the actuals
come from is implementation defined. What happens to the result of a
main function is also implementation defined.
21.a
Implementation defined: Parameter
passing and function return for the main subprogram.
22
or:
23
- A null_statement,
if there is no main subprogram.
23.a
Discussion: For a passive partition,
either there is no environment task, or its sequence_of_statements
is an infinite loop. See E.1.
24
The mechanisms for building and running partitions
are implementation defined. [These might be combined into one operation,
as, for example, in dynamic linking, or ``load-and-go'' systems.]
24.a
Implementation defined: The
mechanisms for building and running partitions.
Dynamic Semantics
25
{execution (program) [partial]}
The execution of a program consists of the execution
of a set of partitions. Further details are implementation defined.
{execution
(partition) [partial]} The execution of
a partition starts with the execution of its environment task, ends when
the environment task terminates, and includes the executions of all tasks
of the partition. [The execution of the (implicit)
task_body
of the environment task acts as a master for all other tasks created
as part of the execution of the partition. When the environment task
completes (normally or abnormally), it waits for the termination of all
such tasks, and then finalizes any remaining objects of the partition.]
25.a
Ramification: The ``further
details'' mentioned above include, for example, program termination --
it is implementation defined. There is no need to define it here; it's
entirely up to the implementation whether it wants to consider the program
as a whole to exist beyond the existence of individual partitions.
25.b
Implementation defined: The
details of program execution, including program termination.
25.c
To be honest: {termination
(of a partition) [partial]} {normal termination
(of a partition) [partial]} {termination (normal)
[partial]} {abnormal termination (of a partition)
[partial]} {termination (abnormal) [partial]}
The execution of the partition terminates (normally
or abnormally) when the environment task terminates (normally or abnormally,
respectively).
Bounded (Run-Time) Errors
26
{bounded error (cause) [partial]}
{Program_Error (raised by failure
of run-time check)} Once the environment
task has awaited the termination of all other tasks of the partition,
any further attempt to create a task (during finalization) is a bounded
error, and may result in the raising of Program_Error either upon creation
or activation of the task.
{unspecified [partial]}
If such a task is activated, it is not specified
whether the task is awaited prior to termination of the environment task.
Implementation Requirements
27
The implementation
shall ensure that all compilation units included in a partition are consistent
with one another, and are legal according to the rules of the language.
27.a
Discussion: The consistency
requirement implies that a partition cannot contain two versions of the
same compilation unit. That is, a partition cannot contain two different
library units with the same full expanded name, nor two different bodies
for the same program unit. For example, suppose we compile the following:
27.b
package A is -- Version 1.
...
end A;
27.c
with A;
package B is
end B;
27.d
package A is -- Version 2.
...
end A;
27.e
with A;
package C is
end C;
27.f
It would be wrong for a partition
containing B and C to contain both versions of A. Typically, the implementation
would require the use of Version 2 of A, which might require the recompilation
of B. Alternatively, the implementation might automatically recompile
B when the partition is built. A third alternative would be an incremental
compiler that, when Version 2 of A is compiled, automatically patches
the object code for B to reflect the changes to A (if there are any relevant
changes -- there might not be any).
27.g
An implementation that supported
fancy version management might allow the use of Version 1 in some circumstances.
In no case can the implementation allow the use of both versions in the
same partition (unless, of course, it can prove that the two versions
are semantically identical).
27.h
Implementation Permissions
28
{active partition}
The kind of partition described in this clause is
known as an
active partition. An implementation is allowed to
support other kinds of partitions, with implementation-defined semantics.
28.a
Implementation defined: The
semantics of any nonactive partitions supported by the implementation.
28.b
Discussion: Annex
E, ``Distributed Systems'' defines the concept of
passive partitions; they may be thought of as a partition without an environment
task, or as one with a particularly simple form of environment task, having
an infinite loop rather than a call on a main subprogram as its sequence_of_statements.
29
An implementation may restrict the kinds of subprograms
it supports as main subprograms. However, an implementation is required
to support all main subprograms that are public parameterless library
procedures.
29.a
Ramification: The implementation
is required to support main subprograms that are procedures declared
by generic_instantiations, as well
as those that are children of library units other than Standard. Generic
units are, of course, not allowed to be main subprograms, since they
are not subprograms.
29.b
Note that renamings are irrelevant
to this rule. This rules says which subprograms (not views) have to be
supported. The implementation can choose any way it wants for the user
to indicate which subprogram should be the main subprogram. An implementation
might allow any name of any view, including those declared by renamings.
Another implementation might require it to be the original name. Another
implementation still might use the name of the source file or some such
thing.
30
If the environment task completes abnormally,
the implementation may abort any dependent tasks.
30.a
Reason: If the implementation
does not take advantage of this permission, the normal action takes place
-- the environment task awaits those tasks.
30.b
The possibility of aborting them
is not shown in the Environment_Task code above, because there
is nowhere to put an exception_handler
that can handle exceptions raised in both the environment declarative_part
and the main subprogram, such that the dependent tasks can be aborted.
If we put an exception_handler in
the body of the environment task, then it won't handle exceptions that
occur during elaboration of the environment declarative_part.
If we were to move those things into a nested block_statement,
with the exception_handler outside
that, then the block_statement would
await the library tasks we are trying to abort.
30.c
Furthermore, this is merely a
permission, and is not fundamental to the model, so it is probably better
to state it separately anyway.
30.d
Note that implementations (and
tools like debuggers) can have modes that provide other behaviors in
addition.
31
8 An implementation may provide inter-partition
communication mechanism(s) via special packages and pragmas. Standard pragmas
for distribution and methods for specifying inter-partition communication are
defined in Annex E, ``Distributed
Systems''. If no such mechanisms are provided, then each partition is isolated
from all others, and behaves as a program in and of itself.
31.a
Ramification: Not providing
such mechanisms is equivalent to disallowing multi-partition programs.
31.b
An implementation may provide mechanisms
to facilitate checking the consistency of library units elaborated in different
partitions; Annex E, ``Distributed
Systems'' does so.
32
9 Partitions are not required
to run in separate address spaces. For example, an implementation might
support dynamic linking via the partition concept.
33
10 An order of elaboration of library_items
that is consistent with the partial ordering defined above does not always ensure
that each library_unit_body is elaborated
before any other compilation unit whose elaboration necessitates that the library_unit_body
be already elaborated. (In particular, there is no requirement that the body
of a library unit be elaborated as soon as possible after the library_unit_declaration
is elaborated, unless the pragmas in subclause 10.2.1
are used.)
34
11 A partition (active or otherwise)
need not have a main subprogram. In such a case, all the work done by the partition
would be done by elaboration of various library_items,
and by tasks created by that elaboration. Passive partitions, which cannot have
main subprograms, are defined in Annex E, ``Distributed
Systems''.
34.a
Ramification: The environment
task is the outermost semantic level defined by the language.
34.b
Standard has no private part. This prevents
strange implementation-dependences involving private children of Standard having
visibility upon Standard's private part. It doesn't matter where the body of
Standard appears in the environment, since it doesn't do anything. See Annex
A, ``Predefined Language Environment''.
34.c
Note that elaboration dependence
is carefully defined in such a way that if (say) the body of something
doesn't exist yet, then there is no elaboration dependence upon the nonexistent
body. (This follows from the fact that ``needed by'' is defined that
way, and the elaboration dependences caused by a pragma
Elaborate or Elaborate_All are defined in terms of ``needed by''.) This
property allows us to use the environment concept both at compile time
and at partition-construction time/run time.
Extensions to Ada 83
34.d
{extensions to Ada 83}
The concept of partitions is new to Ada 95.
34.e
A main subprogram is now optional.
The language-defined restrictions on main subprograms are relaxed.
Wording Changes from Ada 83
34.f
Ada 95 uses the term ``main subprogram''
instead of Ada 83's ``main program'' (which was inherited from Pascal).
This is done to avoid confusion -- a main subprogram is a subprogram,
not a program. The program as a whole is an entirely different thing.
Contents Index Previous Next Legal