Annotated Ada Reference ManualLegal Information
Contents   Index   References   Search   Previous   Next 

13.11.3 Default Storage PoolsPragma Controlled

This paragraph was deleted.{AI05-0229-1} [Pragma Controlled is used to prevent any automatic reclamation of storage (garbage collection) for the objects created by allocators of a given access type.] 


{AI05-0190-1} {AI05-0229-1} The form of a pragma Default_Storage_Pool Controlled is as follows: 
{AI05-0190-1} {AI05-0229-1}   pragma Default_Storage_Pool (storage_pool_indicator);   pragma Controlled(first_subtype_local_name);
Discussion: {AI05-0229-1} Not to be confused with type Finalization.Controlled.
{AI05-0190-1} storage_pool_indicator ::= storage_pool_name | null
{AI05-0190-1} A pragma Default_Storage_Pool is allowed immediately within the visible part of a package_specification, immediately within a declarative_part, or as a configuration pragma. 

Name Resolution Rules

  {AI05-0190-1} The storage_pool_name is expected to be of type Root_Storage_Pool'Class. 

Legality Rules

{AI05-0190-1} {AI05-0229-1} The storage_pool_name shall denote a variable. The first_subtype_local_name of a pragma Controlled shall denote a nonderived access subtype.
  {AI05-0190-1} 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.]
  {AI05-0190-1} {AI05-0262-1} A pragma 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 pragma Default_Storage_Pool.
Reason: This is to prevent confusion in cases like this: 
package Parent is
   pragma Default_Storage_Pool(...);
end Parent;
pragma Default_Storage_Pool(...); -- Illegal!
package Parent.Child is
end Parent.Child;
where the Default_Storage_Pool on Parent.Child would not (if it were legal) override the one in Parent. 

Static Semantics

{AI05-0190-1} {AI05-0229-1} 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. The aspect_definition 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 A pragma Controlled is a representation pragma that specifies the controlled aspect of representation.
Aspect Description for Default_Storage_Pool: Default storage pool for a generic instance.
{AI05-0190-1} {AI05-0229-1} 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.
{AI05-0190-1} 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.]
{AI05-0190-1} If the default pool is nonnull, the Storage_Pool attribute is that pool.
  {AI05-0190-1} [Otherwise, there is no default pool; the standard storage pool is used for the type as described in 13.11.]
Ramification: {AI05-0190-1} {AI05-0229-1} 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.
{AI05-0190-1} {AI05-0229-1} 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.
{AI05-0190-1} 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.
{AI05-0190-1} 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.
{AI05-0190-1} 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. 
Reason: {AI05-0229-1} 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.
Implementation Note: {AI05-0229-1} 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 controlled objects. 
Reason: {AI05-0229-1} 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:
with Ada.Finalization;
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;
    procedure Non_Reentrant;
end P;
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) := ...;
    end Non_Reentrant;
    procedure Finalize(Object : in out My_Controlled) is
    end Finalize;
end P;
with P; use P;
procedure Main is
    ... new My_Controlled ... -- allocate some objects
    ...  forget the pointers to some of them, so they become garbage
end Main;
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 deleted.{AI05-0229-1} 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.
Ramification: {AI05-0229-1} 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. 
Reason: {AI05-0229-1} Controlled means that implementation-provided garbage collection is turned off; if the Storage_Pool is specified, the pool controls whether garbage collection is done. 

Implementation Permissions

{AI05-0190-1} {AI05-0229-1} 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 effect
Discussion: {AI05-0190-1} This matches the required finalization point for such an allocated object. 
33  {AI05-0190-1} 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

This paragraph was deleted.{AI05-0229-1} 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

{AI05-0229-1} 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

{AI05-0190-1} The pragma Default_Storage_Pool is new. 

Wording Changes from Ada 2005

{AI05-0229-1} 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. 

Contents   Index   References   Search   Previous   Next 
Ada-Europe Ada 2005 and 2012 Editions sponsored in part by Ada-Europe