D.14.2 Group Execution Time Budgets
This subclause describes a language-defined package 
to assign execution time budgets to groups of tasks. 
Static Semantics
The following language-defined 
library package exists: 
with System;
with System.Multiprocessors;
package Ada.Execution_Time.Group_Budgets 
is 
  type Group_Budget(CPU : System.Multiprocessors.CPU :=
                             System.Multiprocessors.CPU'First)
    
is tagged limited private;
 
  type Group_Budget_Handler 
is access
       protected procedure (GB : 
in out Group_Budget);
 
  type Task_Array 
is array (Positive 
range <>) 
of
                                  Ada.Task_Identification.Task_Id;
 
  Min_Handler_Ceiling : 
constant System.Any_Priority :=
    
implementation-defined;
 
  procedure Add_Task (GB : 
in out Group_Budget;
                      T  : 
in Ada.Task_Identification.Task_Id);
  
procedure Remove_Task (GB: 
in out Group_Budget;
                         T  : 
in Ada.Task_Identification.Task_Id);
  
function Is_Member (GB : Group_Budget;
                      T : Ada.Task_Identification.Task_Id) 
return Boolean;
  
function Is_A_Group_Member
     (T : Ada.Task_Identification.Task_Id) 
return Boolean;
  
function Members (GB : Group_Budget) 
return Task_Array;
 
  procedure Replenish (GB : 
in out Group_Budget; To : 
in Time_Span);
  
procedure Add (GB : 
in out Group_Budget; Interval : 
in Time_Span);
  
function Budget_Has_Expired (GB : Group_Budget) 
return Boolean;
  
function Budget_Remaining (GB : Group_Budget) 
return Time_Span;
 
  procedure Set_Handler (GB      : 
in out Group_Budget;
                         Handler : 
in Group_Budget_Handler);
  
function Current_Handler (GB : Group_Budget)
     
return Group_Budget_Handler;
  
procedure Cancel_Handler (GB        : 
in out Group_Budget;
                            Cancelled : 
out Boolean);
 
  Group_Budget_Error : 
exception;
 
private
    --  not specified by the language
end Ada.Execution_Time.Group_Budgets;
 The type Group_Budget represents an execution time 
budget to be used by a group of tasks. The type Group_Budget needs finalization
 
(see 
7.6). A task can belong to at most one 
group. Tasks of any priority can be added to a group.
 
 An object of type Group_Budget has an associated 
nonnegative value of type Time_Span known as its 
budget, which 
is initially Time_Span_Zero. The type Group_Budget_Handler identifies 
a protected procedure to be executed by the implementation when the budget 
is 
exhausted, that is, reaches zero. Such a protected procedure 
is called a 
handler.
  
 An object of type Group_Budget also includes a handler, 
which is a value of type Group_Budget_Handler. The handler of the object 
is said to be 
set if it is not null and 
cleared otherwise. 
The handler of all Group_Budget objects is initially cleared. 
 
Dynamic Semantics
 The procedure Add_Task adds the task identified 
by T to the group GB; if that task is already a member of some other 
group, Group_Budget_Error is raised.
 The procedure Remove_Task removes the task identified 
by T from the group GB; if that task is not a member of the group GB, 
Group_Budget_Error is raised. After successful execution of this procedure, 
the task is no longer a member of any group.
 The function Is_Member returns True if the task 
identified by T is a member of the group GB; otherwise, it returns False.
 The function Is_A_Group_Member returns True if the 
task identified by T is a member of some group; otherwise, it returns 
False.
 The function Members returns an array of values 
of type Task_Identification.Task_Id identifying the members of the group 
GB. The order of the components of the array is unspecified.
 The procedure Replenish loads the group budget GB 
with To as the Time_Span value. The exception Group_Budget_Error is raised 
if the Time_Span value To is nonpositive. Any execution on CPU of any 
member of the group of tasks results in the budget counting down, unless 
exhausted. When the budget becomes exhausted (reaches Time_Span_Zero), 
the associated handler is executed if the handler of group budget GB 
is set. Nevertheless, the tasks continue to execute.
 The procedure Add modifies the budget of the group 
GB. A positive value for Interval increases the budget. A negative value 
for Interval reduces the budget, but never below Time_Span_Zero. A zero 
value for Interval has no effect. A call of procedure Add that results 
in the value of the budget going to Time_Span_Zero causes the associated 
handler to be executed if the handler of the group budget GB is set.
 The function Budget_Has_Expired returns True if 
the budget of group GB is exhausted (equal to Time_Span_Zero); otherwise, 
it returns False.
 The function Budget_Remaining returns the remaining 
budget for the group GB. If the budget is exhausted it returns Time_Span_Zero. 
This is the minimum value for a budget.
 The procedure Set_Handler associates the handler 
Handler with the Group_Budget GB: if Handler is null, the handler 
of Group_Budget is cleared; otherwise, it is set.
 A call of Set_Handler for a Group_Budget that already 
has a handler set replaces the handler; if Handler is not null, 
the handler for Group_Budget remains set.
 The function Current_Handler returns the handler 
associated with the group budget GB if the handler for that group budget 
is set; otherwise, it returns null.
 The procedure Cancel_Handler clears the handler 
for the group budget if it is set. Cancelled is assigned True if the 
handler for the group budget was set prior to it being cleared; otherwise, 
it is assigned False.
 The constant Min_Handler_Ceiling is the minimum 
ceiling priority required for a protected object with a handler to ensure 
that no ceiling violation will occur when that handler is invoked.
 The precision of the accounting of task execution 
time to a Group_Budget is the same as that defined for execution-time 
clocks from the parent package.
 As part of the finalization of an object of type 
Group_Budget all member tasks are removed from the group identified by 
that object.
 If a task is a member of a Group_Budget when it 
terminates, then as part of the finalization of the task it is removed 
from the group.
 For all the operations defined in this package, 
Tasking_Error is raised if the task identified by T has terminated, and 
Program_Error is raised if the value of T is Task_Identification.Null_Task_Id.
 An exception propagated from a handler invoked when 
the budget of a group of tasks becomes exhausted has no effect.
Erroneous Execution
 For a call of any of the subprograms 
defined in this package, if the task identified by T no longer exists, 
the execution of the program is erroneous. 
 
Implementation Requirements
 For a given Group_Budget object, the implementation 
shall perform the operations declared in this package atomically with 
respect to any of these operations on the same Group_Budget object. The 
replacement of a handler, by a call of Set_Handler, shall be performed 
atomically with respect to the execution of the handler. 
46  Clearing or setting of the handler of 
a group budget does not change the current value of the budget. Exhaustion 
or loading of a budget does not change whether the handler of the group 
budget is set or cleared.
47  A Group_Budget_Handler can be associated 
with several Group_Budget objects. 
Ada 2005 and 2012 Editions sponsored in part by Ada-Europe