!standard C.7.1 (10) 99-07-27 AI95-00206/02 !class ramification 98-09-29 !status WG9 approved 99-06-12 !status ARG Approved (7-0-0) 98-10-08 !status work item 98-09-29 !status received 98-09-29 !priority Medium !difficulty Easy !subject Ada.Task_Identification.Is_Callable for the environment task !summary Ada.Task_Identification.Is_Callable called with a Task_Id value designating the environment task returns True while the main subprogram is executing and False once the main subprogram has returned and the environment task starts waiting for library-level tasks to terminate. !question What is the behavior of Ada.Task_Identification.Is_Callable for the environment task? In particular, does it change in value from True to False when the main subprogram exits and starts waiting for library-level tasks to terminate? (Yes) !response The note C.7.1(21) says that Ada.Task_Identification.Current_Task can return a Task_Id value designating the environment task. The definition of Is_Callable (in 9.8(2)) is that it is True unless the task is completed or abnormal. The structure of the environment task given in 10.2(10-12), and the dynamic semantics of 10.2(25) tell us that the environment task is completed before waiting for dependent tasks. The erroneous execution case of C.7.1(18) should not apply, as the environment task continues to exist until the partition terminates. Therefore, the value of Ada.Task_Identification.Is_Callable is well defined. It is possible to test the value after the completion of the environment task in a library-level task (while the environment task is waiting for dependent tasks to terminate). Thus it cannot be implemented purely as a return of True at all times. The Ada.Task_Identification.Is_Callable flag can be useful, as a library-level task can use the value to terminate itself once the partition has completed. This is especially important to bullet-proof a reusable package containing a library task. At least one commercial Ada library uses this technique. !ACATS test A C-Test should be created to test this case. !appendix !topic Is_Callable and the environment task. !reference RM95-C.7.1(10);6.0 !reference RM95-C.7.1(21);6.0 !reference RM95-9.9(2);6.0 !reference RM95-9.3(5);6.0 !reference RM95-10.2(8);6.0 !reference RM95-10.2(25);6.0 !from Randy Brukardt 98-08-07 <> !discussion What is the behavior of Ada.Task_Identification.Is_Callable for the environment task? In particular, does it change in value from True to False when the main subprogram exits and starts waiting for library-level tasks to terminate? The note C.7.1(21) makes it clear that it is intended that the package Ada.Task_Identification be able to return and therefore process a Task_Id identifying the environment task. It is easy to get such a Task_Id, just add an object to the elaboration of a library-level package: Environment_Task_Id : Ada.Task_Identification.Task_Id := Ada.Task_Identification.Current_Task; The definition of Is_Callable (C.7.1(10)) refers to the definition of the Callable attribute (9.9(2) "A task is callable unless it is completed or abnormal."). A task is completed when its body is completed. 10.2(8) describes the environment task as elaborating packages and then calling the main subprogram. 10.2(25) describes the execution of a partition. It includes the following statement "When the environment task completes (normally or abnormally), it waits for the termination of all such [library-level] tasks, then finalizes any remaining objects of the partition." When the environment task completes, the other rules would seem to imply that Is_Callable for the environment task would become False. However, some of the best minds in Ada seem to think otherwise; therefore I'm submitting the question to the ARG. The value of Is_Callable would be useful to determine whether the main subprogram has completed. A package with embedded tasks could use this information to determine when to terminate, without requiring any cooperation from the main program. This is of benefit to "canned" packages, which ought to be designed to work even in the face of common user errors. For instance, needing a "Shutdown" routine makes a package more fragile, because it is easy for the user of the package to forget to call the routine (or an exception propagates past the call, causing it not to be called). If a "canned" package includes a task, it is important that the task be able to terminate itself appropriately. Unfortunately, finalization cannot be used for this purpose, since library-level tasks must terminate before any library-level objects are finalized. Therefore, another technique must be used. If the task cannot sit on a terminate alternative (perhaps because it must poll a resource), a function which returns the status of the environment task is another solution - and Ada 95 already has the function. This problem has arisen in Claw in the task which handles Window messages, it is not academic. Randy. ********************************* !topic Is_Callable and the environment task. !reference RM95-C.7.1(10);6.0 !reference RM95-C.7.1(21);6.0 !reference RM95-9.9(2);6.0 !reference RM95-9.3(5);6.0 !reference RM95-10.2(8);6.0 !reference RM95-10.2(25);6.0 !reference 1998-15876.a Randy Brukardt 98-08-07 !from Tucker Taft 98-08-08 <> !discussion > What is the behavior of Ada.Task_Identification.Is_Callable for the > environment task? > In particular, does it change in value from True to False when the main > subprogram > exits and starts waiting for library-level tasks to terminate? I believe it should. Most of our compilers do the "right" thing, but one does not. Fixing this is not a big deal for us. It was just an oversight, and I agree that RM 10.2 gives enough hints to imply that it should go from true to false upon return from the main subprogram. > ... If the task cannot sit on a terminate alternative (perhaps because > it must poll a resource), a function which returns the status of the > environment task is another solution - and Ada 95 already has the function. > > This problem has arisen in Claw in the task which handles Window messages, > it is not academic. This shows that making Is_Callable work "right" for the environment task has value, and hence is worth enforcing. Probably a simple addition to one of the existing ACVC tests for Is_Callable could resolve this, along with an appropriate AI, of course. I presume other vendors will speak up if this is a major implementation burden in some environments, in which case further discussion may be necessary. > Randy. -Tuck ******************************************** !topic Is_Callable and the environment task. !reference RM95-C.7.1(10);6.0 !reference RM95-C.7.1(21);6.0 !reference RM95-9.9(2);6.0 !reference RM95-9.3(5);6.0 !reference RM95-10.2(8);6.0 !reference RM95-10.2(25);6.0 !reference 1998-15876.a Randy Brukardt 1998-8-7 !from Ted Baker 1998-8-9 <> !discussion | What is the behavior of Ada.Task_Identification.Is_Callable for | the environment task? In particular, does it change in value from | True to False when the main subprogram exits and starts waiting | for library-level tasks to terminate? I believe the ARM intentionally leaves this unspecified. ... | The value of Is_Callable would be useful to determine whether the main | subprogram has completed. I can see that it would be useful. Without checking the code carefully, based on what I remember, I guess GNARL would need some modification to give this behavior, but it would not be a big change. --Ted Baker ******************************* !topic Is_Callable and the environment task. !reference RM95-C.7.1(10);6.0 !reference RM95-C.7.1(21);6.0 !reference RM95-9.9(2);6.0 !reference RM95-9.3(5);6.0 !reference RM95-10.2(8);6.0 !reference RM95-10.2(25);6.0 !reference 1998-15876.a Randy Brukardt 1998-8-7 !reference 1998-15878.a Ted Baker 1998-8-9 <> !discussion > >| What is the behavior of Ada.Task_Identification.Is_Callable for >| the environment task? In particular, does it change in value from >| True to False when the main subprogram exits and starts waiting >| for library-level tasks to terminate? > >I believe the ARM intentionally leaves this unspecified. > I don't see what even makes you think that it is unspecified. OK, there is no rule specifically saying what the behaviour of the environment task is, but there are many places where special cases are not specified: it just means that the regular rule applies. This is enforced by C.7.1(21), a *note* (i.e. stressing something that can be deduced from the RM), that says: The function Current_Task and the attribute Caller can return a Task_ID value that identifies the environment task. I take "can" here as merely recognizing a fact, not as an option like "could" or "might". *********************************************************** !topic Is_Callable and the environment task. !reference RM95-C.7.1(10);6.0 !reference RM95-C.7.1(21);6.0 !reference RM95-9.9(2);6.0 !reference RM95-9.3(5);6.0 !reference RM95-10.2(8);6.0 !reference RM95-10.2(25);6.0 !reference 1998-15876.a Randy Brukardt 1998-8-7 !reference 1998-15878.a Ted Baker 1998-8-9 !reference 1998-15881.a Jean-Pierre Rosen 1998-8-11 !from Ted Baker 1998-8-12 <> !discussion | | >| What is the behavior of Ada.Task_Identification.Is_Callable for | >| the environment task? In particular, does it change in value from | >| True to False when the main subprogram exits and starts waiting | >| for library-level tasks to terminate? | > | >I believe the ARM intentionally leaves this unspecified. | > | I don't see what even makes you think that it is unspecified.... Sorry, I was mistaken. I see now that that the ARM '95 specifies more than I remembered, i.e., | 10.2 Program Execution ... | 10 The environment task for a partition has the following structure: | 11 task Environment_Task; | 12 task body Environment_Task is | ... (1) -- The environment declarative_part | -- (that is, the sequence of library_items) goes here. | begin | ... (2) -- Call the main subprogram, if there is one. | end Environment_Task; ... | 20 The sequence_of_statements of the environment task (see (2) above) | consists of either: | 21 A call to the main subprogram, if the partition has one. If the | main subprogram has parameters, they are passed; where the | actuals come from is implementation defined. What happens to the | result of a main function is also implementation defined. | 22 or: | 23 A null_statement, if there is no main subprogram. ... | 9.9 Task and Entry Attributes ... | 2 T'Callable | Yields the value True when the task denoted by T is callable, | and False otherwise; a task is callable unless it is | completed or abnormal. The value of this attribute is of the | predefined type Boolean. --Ted