9.1 Task Units and Task Objects
1
{task declaration}
A task unit is declared by a
task declaration,
which has a corresponding
task_body. A task
declaration may be a
task_type_declaration,
in which case it declares a named task type; alternatively, it may be
a
single_task_declaration, in which case it
defines an anonymous task type, as well as declaring a named task object
of that type.
Syntax
2/2
{
AI95-00345-01}
task_type_declaration ::=
task type defining_identifier [
known_discriminant_part] [
is
[new interface_list with]
task_definition];
3/2
{
AI95-00399-01}
single_task_declaration ::=
task defining_identifier [
is
[new interface_list with]
task_definition];
4
task_definition ::=
{
task_item}
[
private
{
task_item}]
end [
task_identifier]
5/1
6
task_body ::=
task body defining_identifier is
declarative_part
begin
handled_sequence_of_statements
end [
task_identifier];
7
If a task_identifier
appears at the end of a task_definition or
task_body, it shall repeat the defining_identifier.
Legality Rules
8/2
This paragraph was
deleted.{
AI95-00345-01}
{requires a completion
(task_declaration}) [partial]} A task
declaration requires a completion[, which shall be a task_body,]
and every task_body shall be the completion
of some task declaration.
8.a/2
This paragraph
was deleted.To be honest: The
completion can be a pragma Import, if the
implementation supports it.
Static Semantics
9
A
task_definition defines
a task type and its first subtype.
{visible
part (of a task unit) [partial]} The first
list of
task_items of a
task_definition,
together with the
known_discriminant_part,
if any, is called the visible part of the task unit. [
{private
part (of a task unit) [partial]} The optional
list of
task_items after the reserved word
private is called the private part of the task unit.]
9.a
Proof: Private part is defined in Section
8.
9.1/1
{
8652/0029}
{
AI95-00116-01}
For a task declaration without a task_definition,
a task_definition without task_items
is assumed.
9.2/2
{
AI95-00345-01}
{
AI95-00397-01}
{
AI95-00399-01}
{
AI95-00419-01}
For a task declaration with an interface_list,
the task type inherits user-defined primitive subprograms from each progenitor
type (see 3.9.4), in the same way that a
derived type inherits user-defined primitive subprograms from its progenitor
types (see 3.4). If the first parameter of
a primitive inherited subprogram is of the task type or an access parameter
designating the task type, and there is an entry_declaration
for a single entry with the same identifier within the task declaration,
whose profile is type conformant with the prefixed view profile of the
inherited subprogram, the inherited subprogram is said to be implemented
by the conforming task entry.{implemented
(by a task entry) [partial]} {type
conformance (required)}
9.b/2
Ramification: The
inherited subprograms can only come from an interface given as part of
the task declaration.
Legality Rules
9.3/2
{
AI95-00345-01}
{requires a completion
(task_declaration}) [partial]} A task
declaration requires a completion[, which shall be a task_body,]
and every task_body shall be the completion
of some task declaration.
9.c/2
To be honest: The
completion can be a pragma Import, if the
implementation supports it.
9.4/2
{
AI95-00345-01}
{
AI95-00399-01}
[Each interface_subtype_mark
of an interface_list appearing within a task
declaration shall denote a limited interface type that is not a protected
interface.]
9.d/2
Proof: 3.9.4
requires that an interface_list only name
interface types, and limits the descendants of the various kinds of interface
types. Only a limited, task, or synchronized interface can have a task
type descendant. Nonlimited or protected interfaces are not allowed,
as they offer operations that a task does not have.
9.5/2
{
AI95-00397-01}
The prefixed view profile of an explicitly declared
primitive subprogram of a tagged task type shall not be type conformant
with any entry of the task type, if the first parameter of the subprogram
is of the task type or is an access parameter designating the task type.
9.e/2
Reason: This prevents
the existence of two operations with the same name and profile which
could be called with a prefixed view. If the operation was inherited,
this would be illegal by the following rules; this rule puts inherited
and non-inherited routines on the same footing. Note that this only applies
to tagged task types (that is, those with an interface in their declaration);
we do that as there is no problem with prefixed view calls of primitive
operations for “normal” task types, and having this rule
apply to all tasks would be incompatible with Ada 95.
9.6/2
{
AI95-00345-01}
{
AI95-00399-01}
For each primitive subprogram inherited by the
type declared by a task declaration, at most one of the following shall
apply:
9.7/2
- {AI95-00345-01}
the inherited subprogram is overridden with a primitive
subprogram of the task type, in which case the overriding subprogram
shall be subtype conformant with the inherited subprogram and not abstract;
or{subtype conformance (required)}
9.8/2
- {AI95-00345-01}
{AI95-00397-01}
the inherited subprogram is implemented by a single
entry of the task type; in which case its prefixed view profile shall
be subtype conformant with that of the task entry. {subtype
conformance (required)}
9.f/2
Ramification: An
entry may implement two subprograms from the ancestors, one whose first
parameter is of type T and one whose first parameter is of type
access T. That doesn't cause implementation problems because
“implemented by” (unlike “overridden’) probably
entails the creation of wrappers.
9.9/2
If neither applies, the inherited
subprogram shall be a null procedure. {generic
contract issue [partial]} In addition
to the places where Legality Rules normally apply (see 12.3),
these rules also apply in the private part of an instance of a generic
unit.
9.g/2
Reason: Each inherited
subprogram can only have a single implementation (either from overriding
a subprogram or implementing an entry), and must have an implementation
unless the subprogram is a null procedure.
Dynamic Semantics
10
[
{elaboration (task
declaration) [partial]} The elaboration
of a task declaration elaborates the
task_definition.
{elaboration (single_task_declaration)
[partial]} The elaboration of a
single_task_declaration
also creates an object of an (anonymous) task type.]
10.a
Proof: This is redundant with the general
rules for the elaboration of a full_type_declaration
and an object_declaration.
11
{elaboration (task_definition)
[partial]} [The elaboration of a
task_definition
creates the task type and its first subtype;] it also includes the elaboration
of the
entry_declarations in the given order.
12/1
{
8652/0009}
{
AI95-00137-01}
{initialization (of a task object)
[partial]} As part of the initialization of
a task object, any
aspect_clauses representation_clauses
and any per-object constraints associated with
entry_declarations
of the corresponding
task_definition are elaborated
in the given order.
12.a/1
Reason: The only aspect_clauses representation_clauses
defined for task entries are ones that specify the Address of an entry,
as part of defining an interrupt entry. These clearly need to be elaborated
per-object, not per-type. Normally the address will be a function of
a discriminant, if such an Address clause is in a task type rather than
a single task declaration, though it could rely on a parameterless function
that allocates sequential interrupt vectors.
12.b
We do not mention representation pragmas, since
each pragma may have its own elaboration rules.
13
{elaboration (task_body)
[partial]} The elaboration of a
task_body
has no effect other than to establish that tasks of the type can from
then on be activated without failing the Elaboration_Check.
14
[The execution of a
task_body
is invoked by the activation of a task of the corresponding type (see
9.2).]
15
The content of a task
object of a given task type includes:
16
- The values of the discriminants of
the task object, if any;
17
- An entry queue for each entry of the
task object;
17.a
Ramification: "For each entry"
implies one queue for each single entry, plus one for each entry of each
entry family.
18
- A representation of the state of the
associated task.
19/2
2 {
AI95-00382-01}
Other than in an access_definition,
the name of a task unit within Within
the declaration or body of
the a
task unit
, the name of the task unit denotes
the current instance of the unit (see
8.6),
rather than the first subtype of the corresponding task type (and thus
the name cannot be used as a
subtype_mark).
19.a/2
Discussion: {
AI95-00382-01}
It can be used as a subtype_mark
in an anonymous access type. In addition However,
it is possible to refer to some other subtype of the task type within
its body, presuming such a subtype has been declared between the
task_type_declaration
and the
task_body.
20
3 The notation of a
selected_component
can be used to denote a discriminant of a task (see
4.1.3).
Within a task unit, the name of a discriminant of the task type denotes
the corresponding discriminant of the current instance of the unit.
21/2
4 {
AI95-00287-01}
A task type is a limited type (see
7.5), and
hence
precludes use of assignment_statements
and has neither an assignment operation
nor predefined equality operators. If an application needs to
store and exchange task identities, it can do so by defining an access
type designating the corresponding task objects and by using access values
for identification purposes. Assignment is available for such an access
type as for any access type. Alternatively, if the implementation supports
the Systems Programming Annex, the Identity attribute can be used for
task identification (see
C.7.1 C.7).
Examples
22
Examples of declarations
of task types:
23
task type Server is
entry Next_Work_Item(WI : in Work_Item);
entry Shut_Down;
end Server;
24/2
{
AI95-00433-01}
task type Keyboard_Driver(ID : Keyboard_ID := New_ID)
is
new Serial_Device with -- see 3.9.4
entry Read (C :
out Character);
entry Write(C :
in Character);
end Keyboard_Driver;
25
Examples of declarations of single tasks:
26
task Controller is
entry Request(Level)(D : Item); -- a family of entries
end Controller;
27
task Parser is
entry Next_Lexeme(L : in Lexical_Element);
entry Next_Action(A : out Parser_Action);
end;
28
task User; -- has no entries
29
Examples of task objects:
30
Agent : Server;
Teletype : Keyboard_Driver(TTY_ID);
Pool : array(1 .. 10) of Keyboard_Driver;
31
Example of access
type designating task objects:
32
type Keyboard is access Keyboard_Driver;
Terminal : Keyboard := new Keyboard_Driver(Term_ID);
Extensions to Ada 83
32.a/1
{
extensions to Ada 83}
The
syntax rules for task declarations are modified to allow a
known_discriminant_part,
and to allow a private part. They are also modified to allow
entry_declarations
and
aspect_clauses representation_clauses
to be mixed.
Wording Changes from Ada 83
32.b
The syntax rules for tasks have been split up
according to task types and single tasks. In particular: The syntax rules
for task_declaration and task_specification
are removed. The syntax rules for task_type_declaration,
single_task_declaration, task_definition
and task_item are new.
32.c
The syntax rule for task_body
now uses the nonterminal handled_sequence_of_statements.
32.d
The declarative_part
of a task_body is now required; that doesn't
make any real difference, because a declarative_part
can be empty.
Extensions to Ada 95
32.e/2
{
AI95-00345-01}
{
AI95-00397-01}
{
AI95-00399-01}
{
AI95-00419-01}
{extensions to Ada 95} Task
types and single tasks can be derived from one or more interfaces. Entries
of the task type can implement the primitive operations of an interface.
Overriding_indicators can be used to specify
whether or not an entry implements a primitive operation.
Wording Changes from Ada 95
32.f/2
{
8652/0029}
{
AI95-00116-01}
Corrigendum: Clarified that a task type
has an implicit empty task_definition if none
is given.
32.g/2
{
8652/0009}
{
AI95-00137-01}
Corrigendum: Changed representation clauses
to aspect clauses to reflect that they are used for more than just representation.
32.h/2
{
AI95-00287-01}
Revised the note on operations of task types to
reflect that limited types do have an assignment operation, but not copying
(assignment_statements).
32.i/2
{
AI95-00382-01}
Revised the note on use of the name of a task type
within itself to reflect the exception for anonymous access types.