13.11.3 Default Storage PoolsPragma Controlled
This paragraph was
[Pragma Controlled is used to prevent any automatic
reclamation of storage (garbage collection) for the objects created by
of a given access type.]
Not to be confused with type Finalization.Controlled.
Name Resolution Rules
is expected to be of type Root_Storage_Pool'Class.
If the pragma
is used as a configuration pragma, the storage_pool_indicator
shall be null, and it defines the default pool
to be null within all applicable compilation units (see 10.1.5),
except within the immediate scope of another pragma
Default_Storage_Pool. Otherwise, [the pragma occurs immediately within
a sequence of declarations, and] it defines the default pool within the
immediate scope of the pragma to be either null or the pool denoted
by the storage_pool_name,
except within the immediate scope of a later pragma Default_Storage_Pool.
[Thus, an inner pragma overrides an outer one.]
Default_Storage_Pool shall not be used as a configuration pragma that
applies to a compilation unit that is within the immediate scope of another
This is to prevent confusion in cases like this:
package Parent is
pragma Default_Storage_Pool(...); -- Illegal!
package Parent.Child is
the Default_Storage_Pool on Parent.Child would not (if it were legal)
override the one in Parent.
The language-defined aspect Default_Storage_Pool
may be specified for a generic instance; it defines the default pool
for access types within an instance.
The expected type for the Default_Storage_Pool aspect is Root_Storage_Pool'Class.
must be a name that denotes a variable. This aspect overrides any Default_Storage_Pool
pragma that might apply to the generic unit; if the aspect is not specified,
the default pool of the instance is that defined for the generic unit
Controlled is a representation pragma that
specifies the controlled aspect of representation
for Default_Storage_Pool: Default
storage pool for a generic instance.
For nonderived access
types declared in places where the default pool is defined by the pragma
or aspect, their Storage_Pool or Storage_Size attribute is determined
as follows, unless Storage_Pool or Storage_Size is specified for the
type: Garbage collection
is a process that automatically reclaims storage, or moves objects to
a different address, while the objects still exist.
If the default pool is null, the Storage_Size
attribute is defined by the language to be zero. [Therefore, an allocator
for such a type is illegal.]
If the default pool is nonnull, the Storage_Pool
attribute is that pool.
[Otherwise, there is no default pool; the standard
storage pool is used for the type as described in 13.11.]
Default_Storage_Pool is the only way to specify
the storage pool for an anonymous access type Storage
reclamation upon leaving a master is not considered garbage collection
Note that coextensions should be allocated in the
same pool (or on the stack) as the outer object (see 13.11);
the Storage_Pool of the access discriminant (and hence the Default_Storage_Pool)
is supposed to be ignored for coextensions. This matches the required
finalization point for coextensions garbage
collection includes compaction of a pool (“moved to a different
Address”), even if storage reclamation is not done
The default storage pool for an allocator that
occurs within an instance of a generic is defined by the Default_Storage_Pool
aspect of the instantiation (if specified), or by the Default_Storage_Pool
pragma that applied to the generic; the Default_Storage_Pool pragma that
applies to the instantiation is irrelevant.
It is possible to specify the Default_Storage_Pool
aspect for an instantiation such that allocations will fail. For example,
the generic unit might be expecting a pool that supports certain sizes
and alignments, and the one on the instance might be more restrictive.
It is the programmer's responsibility to get this right.
The semantics of the Default_Storage_Pool aspect
are similar to passing a pool object as a generic formal, and putting
pragma Default_Storage_Pool at the top of the generic's visible part,
specifying that formal.
Programs that will be damaged by automatic storage
reclamation are just as likely to be damaged by having objects moved
to different locations in memory. A pragma
Controlled should turn off both flavors of garbage collection.
If garbage collection reclaims the storage of a
controlled object, it should first finalize it. Finalization is not done
when moving an object; any self-relative pointers will have to be updated
by the garbage collector. If an implementation provides garbage collection
for a storage pool containing controlled objects (see 7.6),
then it should provide a means for deferring garbage collection of those
This allows the manager of a resource released
by a Finalize operation to defer garbage collection during its critical
regions; it is up to the author of the Finalize operation to do so. Garbage
collection, at least in some systems, can happen asynchronously with
respect to normal user code. Note that it is not enough to defer garbage
collection during Initialize, Adjust, and Finalize, because the resource
in question might be used in other situations as well. For example:
package P is
type My_Controlled is
new Ada.Finalization.Limited_Controlled with private;
procedure Finalize(Object : in out My_Controlled);
type My_Controlled_Access is access My_Controlled;
package body P is
X : Integer := 0;
A : array(Integer range 1..10) of Integer;
procedure Non_Reentrant is
X := X + 1;
-- If the system decides to do a garbage collection here,
-- then we're in trouble, because it will call Finalize on
-- the collected objects; we essentially have two threads
-- of control erroneously accessing shared variables.
-- The garbage collector behaves like a separate thread
-- of control, even though the user hasn't declared
-- any tasks.
A(X) := ...;
procedure Finalize(Object : in out My_Controlled) is
with P; use P;
procedure Main is
... new My_Controlled ... -- allocate some objects
... forget the pointers to some of them, so they become garbage
It is the user's responsibility
to protect against this sort of thing, and the implementation's responsibility
to provide the necessary operations.
We do not give these operations
names, nor explain their exact semantics, because different implementations
of garbage collection might have different needs, and because garbage
collection is not supported by most Ada implementations, so portability
is not important here. Another reason not to turn off garbage collection
during each entire Finalize operation is that it would create a serial
bottleneck; it might be only part of the Finalize operation that conflicts
with some other resource. It is the intention that the mechanisms provided
be finer-grained than pragma Controlled.
This paragraph was
If a pragma
Controlled is specified for an access type with a standard storage pool,
then garbage collection is not performed for objects in that pool.
If Controlled is not specified, the implementation
may, but need not, perform garbage collection. If Storage_Pool is specified,
then a pragma
Controlled for that type is ignored.
Controlled means that implementation-provided garbage
collection is turned off; if the Storage_Pool is specified, the pool
controls whether garbage collection is done.
An object created by an allocator
that is passed as the actual parameter to an access parameter may be
allocated on the stack, and automatically reclaimed, regardless of the
default pool. An implementation need not
support garbage collection, in which case, a pragma Controlled has no
This matches the required finalization point for
such an allocated object.
Default_Storage_Pool may be used with restrictions
No_Coextensions and No_Access_Parameter_Allocators (see H.4)
to ensure that all allocators
use the default pool.
Wording Changes from Ada 83
Ada 83 used the term “automatic storage reclamation”
to refer to what is known traditionally as “garbage collection”.
Because of the existence of storage pools (see 13.11),
we need to distinguish this from the storage reclamation that might happen
upon leaving a master. Therefore, we now use the term “garbage
collection” in its normal computer-science sense. This has the
additional advantage of making our terminology more accessible to people
outside the Ada world.
Incompatibilities With Ada 2005
Pragma Controlled has been
dropped from Ada, as it has no effect in any known Ada implementations
and it seems to promise capabilities not expected in Ada implementations.
This is usually not an incompatibility, as the pragma merely becomes
unrecognized (with a warning) and can be implemented as an implementation-defined
pragma if desired. However, it is incompatible if it is (now) implemented
as an implementation-defined pragma, someone used this pragma in a unit,
and they also used restriction No_Implementation_Pragmas on that unit.
In that case, the pragma would now violate the restriction; but use of
this pragma (which does nothing) should be very rare, so this is not
a significant issue.
Extensions to Ada 2005
Wording Changes from Ada 2005
The entire discussion of garbage collection (and
especially that of controlled objects) is deleted. Ada 2012 provides
subpools (see 13.11.4) for storage management
of objects, including controlled objects, a mechanism which is much more
predictable than garbage collection. Note that no version of Ada allows
early finalization of controlled objects (other than via the use of Unchecked_Deallocation
or Unchecked_Deallocate_Subpool), so that garbage collection of such
objects would be ineffective in the standard mode anyway.
Ada 2005 and 2012 Editions sponsored in part by Ada-Europe