13.11.3 Pragma Controlled
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.] 
Syntax
2
The form of 
a pragma Controlled is as follows: 
3
  pragma Controlled(
first_subtype_local_name); 
 
3.a
Discussion: Not to be confused with type 
Finalization.Controlled. 
Legality Rules
4
The first_subtype_local_name 
of a pragma Controlled shall denote a non-derived 
access subtype. 
Static Semantics
5
{representation pragma 
(Controlled) [partial]} {pragma, 
representation (Controlled) [partial]} A 
pragma Controlled is a representation pragma 
{aspect of representation (controlled) 
[partial]} {controlled 
(aspect of representation)} that specifies 
the 
controlled aspect of representation.
 
6
{garbage collection} 
Garbage collection is a process that automatically 
reclaims storage, or moves objects to a different address, while the 
objects still exist. 
 
6.a
Ramification: Storage reclamation upon 
leaving a master is not considered garbage collection.
6.b
Note that garbage collection includes compaction 
of a pool (“moved to a different Address”), even if storage 
reclamation is not done. 
6.c
Reason: 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. 
6.d
Implementation Note: 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. 
 
6.e
Reason: 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: 
6.f
with Ada.Finalization;
package P is
6.g
    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;
6.h
    procedure Non_Reentrant;
6.i
private
    ...
end P;
6.j
package body P is
    X : Integer := 0;
    A : array(Integer range 1..10) of Integer;
6.k
    procedure Non_Reentrant is
    begin
        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;
6.l
    procedure Finalize(Object : in out My_Controlled) is
    begin
        Non_Reentrant;
    end Finalize;
end P;
6.m
with P; use P;
procedure Main is
begin
    ... new My_Controlled ... -- allocate some objects
    ...  forget the pointers to some of them, so they become garbage
    Non_Reentrant;
end Main;
  
6.n
It is the user's responsibility to protect against 
this sort of thing, and the implementation's responsibility to provide 
the necessary operations.
6.o
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. 
7
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. 
7.a
Ramification: 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. 
7.b
Reason: 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
8
An implementation need not support garbage collection, 
in which case, a pragma Controlled has no effect. 
Wording Changes from Ada 83
8.a
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.