From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=0.2 required=5.0 tests=BAYES_00,INVALID_MSGID, REPLYTO_WITHOUT_TO_CC autolearn=no autolearn_force=no version=3.4.4 X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 103376,f92fbb4a0420dd57 X-Google-Attributes: gid103376,public From: ncohen@watson.ibm.com (Norman H. Cohen) Subject: Re: some questions re. Ada/GNAT from a C++/GCC user Date: 1996/04/01 Message-ID: <4jp17p$17vn@watnews1.watson.ibm.com>#1/1 X-Deja-AN: 145254814 distribution: world references: <4je9ju$174r@watnews1.watson.ibm.com> <4jhe1v$m0g@dayuc.dayton.saic.com> organization: IBM T.J. Watson Research Center reply-to: ncohen@watson.ibm.com newsgroups: comp.lang.ada Date: 1996-04-01T00:00:00+00:00 List-Id: In article <4jhe1v$m0g@dayuc.dayton.saic.com>, John G. Volan writes: |> An Ada programmer would counter that, in Ada, some variables might be |> instances of _task_ types. By definition, a task object gets created |> when its declaration is elaborated, but it does not get _activated_ |> (i.e., it doesn't start executing its statements) until you hit the |> "begin" of the enclosing block. This guarantees that everything in the |> enclosing declarative region is elaborated before any a task starts up. No, it doesn't guarantee that, because a task can also be created by an ALLOCATOR in the declarative part, in which case it is activated immediately. Program_Error results if the task is activated before its task body has been elaborated, so the fact that declarations in a declarative part are elaborated in order is sufficient to guarantee that any declaration referred to by the task unit has already been elaborated by the time a task of the corresponding task type is activated. |> In fact, _all_ the tasks in a declarative region are activated by the |> "begin", simultaneously. (Or virtually simultaneously. The point is, |> Ada does not prescribe any particular order of activation, and does not |> preclude truly simultaneous activation if the underlying run time |> environment can support it.) In effect, if a declarative region |> contains tasks, then there is a synchronization point at the "begin" |> which the Ada programmer can rely on. All these complicated rules about activation (which originated in Ada 83) are actually there just for the sake of exception handling: If any declared task fails during activation (i.e., raises an exception during the elaboration of its task body's declarative part), Tasking_Error will be raised in the associated sequence of statements. Placing the nominal point of activation just after the "begin" in the frame containing the declaration means that the exception handlers of that frame can catch the exception. (This would not be the case if the Tasking_Error were raised in declarative part.) Forcing the master frame to wait until all tasks declared in the frame have been activated (or have died trying) allows Tasking_Error to be raised exactly once in the master if one or more dependent tasks have failed to activate. There are at least three ways the rules of Ada could have allowed the creator of a task to be informed about an unhandled exception in a task it has created: (a) Not at all. In other words, the created task could die unnoticed, like Eleanor Rigby. (b) Asynchronously. An exception could be raised, at an unpredictable time and place, in the creating task. (c) Synchronously. An exception could be raised, if at all, at a predicatable time and place in the creating task. Jean Ichbiah correctly saw the chaos that could result from approach (b). He chose approach (c) for an exception occuring while the child task was still elaborating the declarative part of its task body and (a) for an exception occuring once the child task entered the sequence of statements of its task body. The problem with applying approach (a) in the declarative part is that there is no way to handle the exception before the execution of the task body is abandoned, since the handlers in the task body do not apply to the declarative part. Once the child has reached adulthood, and is capable of handling its own exceptions, its parent is no longer responsible for its sins. (Anyone who has debugged a program in which a task raised an unhandled exception has quickly learned the value of adding a handler such as when others => Display_Error_Message ("Task of type XYZ abandoned due to unhandled exception."); to each task body.) -- Norman H. Cohen ncohen@watson.ibm.com