C.7.2 The Package Task_Attributes
The following language-defined
generic library package exists:
Attribute is private
Initial_Value : in
Attribute_Handle is access all
Value(T : Task_Id := Current_Task)
Reference(T : Task_Id := Current_Task)
Set_Value(Val : in
T : in
Task_Id := Current_Task);
Reinitialize(T : in
Task_Id := Current_Task);
When an instance of Task_Attributes is elaborated
in a given active partition, an object of the actual type corresponding
to the formal type Attribute is implicitly created for each task (of
that partition) that exists and is not yet terminated. This object acts
as a user-defined attribute of the task. A task created previously in
the partition and not yet terminated has this attribute from that point
on. Each task subsequently created in the partition will have this attribute
when created. In all these cases, the initial value of the given attribute
The Value operation returns the value of the corresponding
attribute of T.
The Reference operation returns an access value that
designates the corresponding attribute of T.
The Set_Value operation performs any finalization
on the old value of the attribute of T and assigns Val to that attribute
The effect of the Reinitialize operation is the same
as Set_Value where the Val parameter is replaced with Initial_Value.
Implementation Note: In most cases, the
attribute memory can be reclaimed at this point.
For all the operations declared
in this package, Tasking_Error is raised if the task identified by T
Program_Error is raised if the value
of T is Null_Task_Id.
After a task has terminated, all of its attributes
are finalized, unless they have been finalized earlier. When the master
of an instantiation of Ada.Task_Attributes is finalized, the corresponding
attribute of each task is finalized, unless it has been finalized earlier.
Reason: This is
necessary so that a task attribute does not outlive its type. For instance,
that's possible if the instantiation is nested, and the attribute is
on a library-level task.
task owning an attribute cannot, in general, finalize that attribute.
That's because the attributes are finalized after the task is
terminated; moreover, a task may have attributes as soon as it is created;
the task may never even have been activated.
Bounded (Run-Time) Errors
If the package Ada.Task_Attributes
is instantiated with a controlled type and the controlled type has user-defined
Adjust or Finalize operations that in turn access task attributes by
any of the above operations, then a call of Set_Value of the instantiated
package constitutes a bounded error. The call may perform as expected
or may result in forever blocking the calling task and subsequently some
or all tasks of the partition.
It is erroneous to dereference
the access value returned by a given call on Reference after a subsequent
call on Reinitialize for the same task attribute, or after the associated
Reason: This allows the storage to be
reclaimed for the object associated with an attribute upon Reinitialize
or task termination.
If a value of Task_Id is passed
as a parameter to any of the operations declared in this package and
the corresponding task object no longer exists, the execution of the
program is erroneous.
access Accesses to a task attribute attributes via a value of type Attribute_Handle is are erroneous if executed concurrently with another
such access each
other or a
calls of any of the operations declared
in package Task_Attributes. An access to
a task attribute is erroneous if executed concurrently with or after
the finalization of the task attribute.
Reason: There is
no requirement of atomicity on accesses via a value of type Attribute_Handle.
task attribute can only be accessed after finalization through a value
of type Attribute_Handle. Operations in package Task_Attributes cannot
be used to access a task attribute after finalization, because either
the master of the instance has been or is in the process of being left
(in which case the instance is out of scope and thus cannot be called),
or the associated task is already terminated (in which case Tasking_Error
is raised for any attempt to call a task attribute operation).
For a given attribute of a given task, the The
implementation shall perform the operations declared
in this package each of the above operations
for a given attribute of a given task
atomically with respect
to any of these operations of other
of the above operations for
the same attribute of the same task.
The granularity of any locking mechanism necessary
to achieve such atomicity is implementation defined.
Granularity of locking for Task_Attributes.
Ramification: Hence, other than by dereferencing
an access value returned by Reference, an attribute of a given task can
be safely read and updated concurrently by multiple tasks.
After When a
task attributes are finalized terminates
the implementation shall finalize all attributes
of the task, and
reclaim any other
associated with the attributes.
The implementation shall document the limit on the
number of attributes per task, if any, and the limit on the total storage
for attribute values per task, if such a limit exists.
In addition, if these limits can be configured, the
implementation shall document how to configure them.
was deleted.Implementation defined:
on the number and size of task attributes, and how to configure them. Implementation-defined
aspects of Task_Attributes.
For package Task_Attributes, limits
on the number and size of task attributes, and how to configure any limits.
The implementation shall document the following metrics: A task calling
the following subprograms shall execute at in
a sufficiently high priority as to not be preempted during the measurement
period. This period shall start just before issuing the call and end
just after the call completes. If the attributes of task T are accessed
by the measurement tests, no other task shall access attributes of that
task during the measurement period. For all measurements described here,
the Attribute type shall be a scalar type
size is equal to the size of the predefined type
Integer integer size
. For each measurement,
two cases shall be documented: one where the accessed attributes are
of the calling task [(that is, the default value for the T parameter
is used)], and the other, where T identifies another, non-terminated,
The following calls
(to subprograms in the Task_Attributes package) shall be measured:
a call to Value, where the return value is Initial_Value;
a call to Value, where the return value is not
equal to Initial_Value;
a call to Reference, where the return value designates
a value equal to Initial_Value;
a call to Reference, where the return value designates
a value not equal to Initial_Value;
a call to Set_Value where the Val parameter is not equal to Initial_Value
and the old attribute value is equal to Initial_Value;.
a call to Set_Value where the Val parameter is
not equal to Initial_Value and the old attribute value is not equal to
The metrics for the Task_Attributes
An implementation need not actually create the object
corresponding to a task attribute until its value is set to something
other than that of Initial_Value, or until Reference is called for the
task attribute. Similarly, when the value of the attribute is to be reinitialized
to that of Initial_Value, the object may instead be finalized and its
storage reclaimed, to be recreated when needed later. While the object
does not exist, the function Value may simply return Initial_Value, rather
than implicitly creating the object.
Discussion: The effect of this permission
can only be observed if the assignment operation for the corresponding
type has side-effects.
This permission means that even though every task has every attribute,
storage need only be allocated for those attributes for
which function Reference has been invoked that
have been Reference'd
or set to a value other than that of Initial_Value.
An implementation is allowed to place restrictions
on the maximum number of attributes a task may have, the maximum size
of each attribute, and the total storage size allocated for all the attributes
of a task.
Some implementations are targeted to domains in which memory use at run
time must be completely deterministic. For such implementations, it is
recommended that the storage for task attributes will be pre-allocated
statically and not from the heap. This can be accomplished by either
placing restrictions on the number and the size of the task's
attributes of a task
, or by using
the pre-allocated storage for the first N attribute objects, and the
heap for the others. In the latter case, N should be documented.
If the target domain requires deterministic
memory use at run time, storage for task attributes should be pre-allocated
statically and the number of attributes pre-allocated should be documented.
don't mention “restrictions on the size and number” (that
is, limits) in the text for the Annex, because it is covered by the Documentation
Requirement above, and we try not to repeat requirements in the Annex
(they're enough work to meet without having to do things twice).
Finalization of task attributes and reclamation
of associated storage should be performed as soon as possible after task
Finalization of task attributes and
reclamation of associated storage should be performed as soon as possible
after task termination.
This is necessary because the normative wording
only says that attributes are finalized “after” task termination.
Without this advice, waiting until the instance is finalized would meet
the requirements (it is after termination, but may be a very long time
after termination). We can't say anything more specific than this, as
we do not want to require the overhead of an interaction with the tasking
system to be done at a specific point.
12 An attribute always exists (after instantiation),
and has the initial value. It need not occupy memory until the first
operation that potentially changes the attribute value. The same holds
true after Reinitialize.
13 The result of the Reference function
should be used with care; it is always safe to use that result in the
task body whose attribute is being accessed. However, when the result
is being used by another task, the programmer must make sure that the
task whose attribute is being accessed is not yet terminated. Failing
to do so could make the program execution erroneous.
As specified in C.7.1,
if the parameter T (in a call on a subprogram of an instance of this
package) identifies a nonexistent task, the execution of the program
Wording Changes from Ada 95
Corrigendum: Clarified that use of task
attribute operations from within a task attribute operation (by an Adjust
or Finalize call) is a bounded error, and that concurrent use of attribute
handles is erroneous.
Clarified the wording so that the finalization
takes place after the termination of the task or when the instance is
finalized (whichever is sooner).
Ada 2005 and 2012 Editions sponsored in part by Ada-Europe