* Finalization of library level tasks @ 2018-04-15 13:40 Dmitry A. Kazakov 2018-04-15 14:02 ` Jeffrey R. Carter 0 siblings, 1 reply; 89+ messages in thread From: Dmitry A. Kazakov @ 2018-04-15 13:40 UTC (permalink / raw) I vaguely remember a discussion regarding this issue but cannot find it. The question is finalization of a task declared at the library level: task type Worker_Type is entry Quit; end Worker_Type; type Worker_Type_Ptr is access Worker_Type; type T is new Ada.Finalization.Limited_Controlled with record Worker : Worker_Type_Ptr; end record; procedure Finalize (X : in out T) is begin X.Worker.Quit; end Finalize; When an instance of T is declared in a library level package, then Finalize is never called, I guess because the task must terminate first due to some rules about its masters. Is there a way to work this around? -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: Finalization of library level tasks 2018-04-15 13:40 Finalization of library level tasks Dmitry A. Kazakov @ 2018-04-15 14:02 ` Jeffrey R. Carter 2018-04-15 14:12 ` Dmitry A. Kazakov 0 siblings, 1 reply; 89+ messages in thread From: Jeffrey R. Carter @ 2018-04-15 14:02 UTC (permalink / raw) On 04/15/2018 03:40 PM, Dmitry A. Kazakov wrote: > > When an instance of T is declared in a library level package, then Finalize is > never called, I guess because the task must terminate first due to some rules > about its masters. The rule is that finalization occurs after all dependent tasks have terminated, presumably so a task cannot access a finalized object. > Is there a way to work this around? That depends on the problem, but usually a design can be reworked to provide for termination of tasks. -- Jeff Carter "Well, a gala day is enough for me. I don't think I can handle any more." Duck Soup 93 ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: Finalization of library level tasks 2018-04-15 14:02 ` Jeffrey R. Carter @ 2018-04-15 14:12 ` Dmitry A. Kazakov 2018-04-15 14:54 ` Jeffrey R. Carter 0 siblings, 1 reply; 89+ messages in thread From: Dmitry A. Kazakov @ 2018-04-15 14:12 UTC (permalink / raw) On 2018-04-15 16:02, Jeffrey R. Carter wrote: > On 04/15/2018 03:40 PM, Dmitry A. Kazakov wrote: >> >> When an instance of T is declared in a library level package, then >> Finalize is never called, I guess because the task must terminate >> first due to some rules about its masters. > > The rule is that finalization occurs after all dependent tasks have > terminated, presumably so a task cannot access a finalized object. There is only environment task. >> Is there a way to work this around? > > That depends on the problem, but usually a design can be reworked to > provide for termination of tasks. The problem is that Finalize is called when the object is declared in a nested scope: procedure Main is Data : X; begin Data.Worker := new Worker_Type; end Main; -- Finalize is called (and terminates the task) This does not work: package Library_Level is Data : X; end Library_Level; with Library_Level; procedure Main is begin Library_Level.Data.Worker := new Worker_Type; end Main; -- Finalize is not called (presumably waiting for the task) -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: Finalization of library level tasks 2018-04-15 14:12 ` Dmitry A. Kazakov @ 2018-04-15 14:54 ` Jeffrey R. Carter 2018-04-15 15:15 ` Dmitry A. Kazakov 0 siblings, 1 reply; 89+ messages in thread From: Jeffrey R. Carter @ 2018-04-15 14:54 UTC (permalink / raw) On 04/15/2018 04:12 PM, Dmitry A. Kazakov wrote: > > The problem is that Finalize is called when the object is declared in a nested > scope: > > procedure Main is > Data : X; > begin > Data.Worker := new Worker_Type; > end Main; -- Finalize is called (and terminates the task) > > This does not work: > > package Library_Level is > Data : X; > end Library_Level; > > with Library_Level; > procedure Main is > begin > Library_Level.Data.Worker := new Worker_Type; > end Main; -- Finalize is not called (presumably waiting for the task) A task declared by an allocator (usually) depends on the thing that the access type is declared in; here, that's a library-level pkg. An object declaration such as Data goes out of scope when the thing that it's declared in goes away. In a procedure, the procedure can end and Data can be finalized, even though Data.Worker.all is still running. You might, for example, copy Data.Worker to another variable of the access type that will exist after the procedure call ends. Or you may want the task to exist and run with no way to refer to it; tasks in worker pools often work this way. When Data is declared in a library-level pkg, it's finalized when the pkg goes out of scope, which doesn't happen until all library-level tasks have terminated. Since Data.Worker has a library-level access type, Data.Worker.all is a library-level task. -- Jeff Carter "Well, a gala day is enough for me. I don't think I can handle any more." Duck Soup 93 ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: Finalization of library level tasks 2018-04-15 14:54 ` Jeffrey R. Carter @ 2018-04-15 15:15 ` Dmitry A. Kazakov 2018-04-15 15:46 ` AdaMagica 2018-04-25 23:46 ` Randy Brukardt 0 siblings, 2 replies; 89+ messages in thread From: Dmitry A. Kazakov @ 2018-04-15 15:15 UTC (permalink / raw) On 2018-04-15 16:54, Jeffrey R. Carter wrote: > On 04/15/2018 04:12 PM, Dmitry A. Kazakov wrote: >> >> The problem is that Finalize is called when the object is declared in >> a nested scope: >> >> procedure Main is >> Data : X; >> begin >> Data.Worker := new Worker_Type; >> end Main; -- Finalize is called (and terminates the task) >> >> This does not work: >> >> package Library_Level is >> Data : X; >> end Library_Level; >> >> with Library_Level; >> procedure Main is >> begin >> Library_Level.Data.Worker := new Worker_Type; >> end Main; -- Finalize is not called (presumably waiting for the task) > > A task declared by an allocator (usually) depends on the thing that the > access type is declared in; here, that's a library-level pkg. > > An object declaration such as Data goes out of scope when the thing that > it's declared in goes away. In a procedure, the procedure can end and > Data can be finalized, even though Data.Worker.all is still running. You > might, for example, copy Data.Worker to another variable of the access > type that will exist after the procedure call ends. Or you may want the > task to exist and run with no way to refer to it; tasks in worker pools > often work this way. That would not work because the task actually has an access discriminant pointing the container type. > When Data is declared in a library-level pkg, it's finalized when the > pkg goes out of scope, which doesn't happen until all library-level > tasks have terminated. Since Data.Worker has a library-level access > type, Data.Worker.all is a library-level task. Yes. The problem is the order of finalization. For some unclear reason the task's access type is attempted before the object that contains that access type because they are in the same scope. The effect is that task termination is requested prematurely. I hoped that there is some trick, e.g. fooling the accessibility rules of the access type, some sort of Unchecked_Allocation. Ada 83 had pragma Controlled to require the compiler to keep its hands off, alas, it was removed. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: Finalization of library level tasks 2018-04-15 15:15 ` Dmitry A. Kazakov @ 2018-04-15 15:46 ` AdaMagica 2018-04-15 15:53 ` Dmitry A. Kazakov ` (2 more replies) 2018-04-25 23:46 ` Randy Brukardt 1 sibling, 3 replies; 89+ messages in thread From: AdaMagica @ 2018-04-15 15:46 UTC (permalink / raw) Am Sonntag, 15. April 2018 17:15:22 UTC+2 schrieb Dmitry A. Kazakov: > e.g. fooling the accessibility rules of the access type, some sort of > Unchecked_Allocation. Ada 83 had pragma Controlled to require the > compiler to keep its hands off, alas, it was removed. This pragma was never implemented by any compiler (because there never was a garbage collector implemented and the pragma was intended to tell the GC to keep its hand off). ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: Finalization of library level tasks 2018-04-15 15:46 ` AdaMagica @ 2018-04-15 15:53 ` Dmitry A. Kazakov 2018-04-15 17:17 ` AdaMagica 2018-04-19 20:39 ` G. B. 2 siblings, 0 replies; 89+ messages in thread From: Dmitry A. Kazakov @ 2018-04-15 15:53 UTC (permalink / raw) On 2018-04-15 17:46, AdaMagica wrote: > Am Sonntag, 15. April 2018 17:15:22 UTC+2 schrieb Dmitry A. Kazakov: >> e.g. fooling the accessibility rules of the access type, some sort of >> Unchecked_Allocation. Ada 83 had pragma Controlled to require the >> compiler to keep its hands off, alas, it was removed. > > This pragma was never implemented by any compiler (because there never was a garbage collector implemented and the pragma was intended to tell the GC to keep its hand off). It would be perfectly suitable for the purpose of explicitly forbidding any internal bookkeeping. I hoped that pragma Convention (C, Pointer) would have same effect, but it does not. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: Finalization of library level tasks 2018-04-15 15:46 ` AdaMagica 2018-04-15 15:53 ` Dmitry A. Kazakov @ 2018-04-15 17:17 ` AdaMagica 2018-04-15 17:40 ` Dmitry A. Kazakov 2018-04-19 20:39 ` G. B. 2 siblings, 1 reply; 89+ messages in thread From: AdaMagica @ 2018-04-15 17:17 UTC (permalink / raw) task body Worker_Type is begin loop select accept Quit; exit; or terminate; end select; end loop; end Worker_Type; procedure Finalize (X: in out T) is begin if X.Worker'Callable then X.Worker.Quit; end if; end Finalize; ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: Finalization of library level tasks 2018-04-15 17:17 ` AdaMagica @ 2018-04-15 17:40 ` Dmitry A. Kazakov 2018-04-15 19:32 ` Egil H H ` (2 more replies) 0 siblings, 3 replies; 89+ messages in thread From: Dmitry A. Kazakov @ 2018-04-15 17:40 UTC (permalink / raw) On 2018-04-15 19:17, AdaMagica wrote: > task body Worker_Type is > begin > loop > select > accept Quit; > exit; > or > terminate; > end select; > end loop; > end Worker_Type; > > procedure Finalize (X: in out T) is > begin > if X.Worker'Callable then > X.Worker.Quit; > end if; > end Finalize; This task will hang in the select statement. Terminate alternative is almost always useless because it cannot be mixed with "else" or "delay". If there were a way to check within the task if its completion has been requested your solution would work. Terminate should have been a normal predefined entry: task body T is begin select accept T'Terminate; exit; or ... -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: Finalization of library level tasks 2018-04-15 17:40 ` Dmitry A. Kazakov @ 2018-04-15 19:32 ` Egil H H 2018-04-15 20:09 ` Dmitry A. Kazakov 2018-04-16 5:19 ` J-P. Rosen 2018-04-16 9:19 ` AdaMagica 2 siblings, 1 reply; 89+ messages in thread From: Egil H H @ 2018-04-15 19:32 UTC (permalink / raw) On Sunday, April 15, 2018 at 7:40:38 PM UTC+2, Dmitry A. Kazakov wrote: > > Terminate alternative is almost always useless because it cannot be > mixed with "else" or "delay". If there were a way to check within the > task if its completion has been requested For library level tasks: loop select accept Some_Rendezvous; or delay Some_Interval; end select; exit when not Ada.Task_Identification.Is_Callable (Ada.Task_Identification.Environment_Task); end loop; ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: Finalization of library level tasks 2018-04-15 19:32 ` Egil H H @ 2018-04-15 20:09 ` Dmitry A. Kazakov 2018-04-25 23:49 ` Randy Brukardt 0 siblings, 1 reply; 89+ messages in thread From: Dmitry A. Kazakov @ 2018-04-15 20:09 UTC (permalink / raw) On 2018-04-15 21:32, Egil H H wrote: > On Sunday, April 15, 2018 at 7:40:38 PM UTC+2, Dmitry A. Kazakov wrote: >> >> Terminate alternative is almost always useless because it cannot be >> mixed with "else" or "delay". If there were a way to check within the >> task if its completion has been requested > > For library level tasks: > > loop > select > accept Some_Rendezvous; > or > delay Some_Interval; > end select; > > exit when not Ada.Task_Identification.Is_Callable > (Ada.Task_Identification.Environment_Task); > > end loop; Yes, that is what I was looking for. T'Callable on the task itself does the trick. Apparently task being terminated is not callable. Thanks. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: Finalization of library level tasks 2018-04-15 20:09 ` Dmitry A. Kazakov @ 2018-04-25 23:49 ` Randy Brukardt 0 siblings, 0 replies; 89+ messages in thread From: Randy Brukardt @ 2018-04-25 23:49 UTC (permalink / raw) "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message news:pb0bho$p1e$1@gioia.aioe.org... > On 2018-04-15 21:32, Egil H H wrote: >> On Sunday, April 15, 2018 at 7:40:38 PM UTC+2, Dmitry A. Kazakov wrote: >>> >>> Terminate alternative is almost always useless because it cannot be >>> mixed with "else" or "delay". If there were a way to check within the >>> task if its completion has been requested >> >> For library level tasks: >> >> loop >> select >> accept Some_Rendezvous; >> or >> delay Some_Interval; >> end select; >> exit when not Ada.Task_Identification.Is_Callable >> (Ada.Task_Identification.Environment_Task); >> end loop; > > Yes, that is what I was looking for. T'Callable on the task itself does > the trick. Apparently task being terminated is not callable. Callable becomes False when a task is completed. That happens before finalization and before termination. The environment task completes when the main subprogram exits, and you can test that as above. Randy. ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: Finalization of library level tasks 2018-04-15 17:40 ` Dmitry A. Kazakov 2018-04-15 19:32 ` Egil H H @ 2018-04-16 5:19 ` J-P. Rosen 2018-04-16 7:30 ` Dmitry A. Kazakov 2018-04-16 9:19 ` AdaMagica 2 siblings, 1 reply; 89+ messages in thread From: J-P. Rosen @ 2018-04-16 5:19 UTC (permalink / raw) Le 15/04/2018 à 19:40, Dmitry A. Kazakov a écrit : > Terminate alternative is almost always useless because it cannot be > mixed with "else" or "delay". And make termination undecidable? Come on! -- J-P. Rosen Adalog 2 rue du Docteur Lombard, 92441 Issy-les-Moulineaux CEDEX Tel: +33 1 45 29 21 52, Fax: +33 1 45 29 25 00 http://www.adalog.fr ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: Finalization of library level tasks 2018-04-16 5:19 ` J-P. Rosen @ 2018-04-16 7:30 ` Dmitry A. Kazakov 2018-04-16 7:55 ` J-P. Rosen 0 siblings, 1 reply; 89+ messages in thread From: Dmitry A. Kazakov @ 2018-04-16 7:30 UTC (permalink / raw) On 16/04/2018 07:19, J-P. Rosen wrote: > Le 15/04/2018 à 19:40, Dmitry A. Kazakov a écrit : >> Terminate alternative is almost always useless because it cannot be >> mixed with "else" or "delay". > And make termination undecidable? Come on! Why? Terminate should be a predefined entry the task master calls to. Anyway since T'Callable seems working, there is no need to use the terminate alternative ever. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: Finalization of library level tasks 2018-04-16 7:30 ` Dmitry A. Kazakov @ 2018-04-16 7:55 ` J-P. Rosen 2018-04-16 8:13 ` Dmitry A. Kazakov 0 siblings, 1 reply; 89+ messages in thread From: J-P. Rosen @ 2018-04-16 7:55 UTC (permalink / raw) Le 16/04/2018 à 09:30, Dmitry A. Kazakov a écrit : > On 16/04/2018 07:19, J-P. Rosen wrote: >> Le 15/04/2018 à 19:40, Dmitry A. Kazakov a écrit : >>> Terminate alternative is almost always useless because it cannot be >>> mixed with "else" or "delay". >> And make termination undecidable? Come on! > > Why? Terminate should be a predefined entry the task master calls to. If you allowed an else (or delay) alternative together with a terminate, that alternative would be selected, and the task could in turn wake-up its descendents... > Anyway since T'Callable seems working, there is no need to use the > terminate alternative ever. > No, T'Callable becomes false AFTER the terminate has been selected. -- J-P. Rosen Adalog 2 rue du Docteur Lombard, 92441 Issy-les-Moulineaux CEDEX Tel: +33 1 45 29 21 52, Fax: +33 1 45 29 25 00 http://www.adalog.fr ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: Finalization of library level tasks 2018-04-16 7:55 ` J-P. Rosen @ 2018-04-16 8:13 ` Dmitry A. Kazakov 2018-04-16 8:32 ` J-P. Rosen 0 siblings, 1 reply; 89+ messages in thread From: Dmitry A. Kazakov @ 2018-04-16 8:13 UTC (permalink / raw) On 16/04/2018 09:55, J-P. Rosen wrote: > Le 16/04/2018 à 09:30, Dmitry A. Kazakov a écrit : >> On 16/04/2018 07:19, J-P. Rosen wrote: >>> Le 15/04/2018 à 19:40, Dmitry A. Kazakov a écrit : >>>> Terminate alternative is almost always useless because it cannot be >>>> mixed with "else" or "delay". >>> And make termination undecidable? Come on! >> >> Why? Terminate should be a predefined entry the task master calls to. > If you allowed an else (or delay) alternative together with a terminate, > that alternative would be selected, and the task could in turn wake-up > its descendents... You would terminate descendants (grandchildren) from the rendezvous with the child's Terminate: select ... or terminate do -- Hidden rendezvous body ... terminate all descendants end Terminate; else ... spawn new descendants end select; >> Anyway since T'Callable seems working, there is no need to use the >> terminate alternative ever. >> > No, T'Callable becomes false AFTER the terminate has been selected. So GNAT implementation is wrong and this one is illegal? task body T is begin loop exit when not T'Callable; ... -- Do something end loop; end T; -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: Finalization of library level tasks 2018-04-16 8:13 ` Dmitry A. Kazakov @ 2018-04-16 8:32 ` J-P. Rosen 2018-04-16 15:26 ` Dmitry A. Kazakov 0 siblings, 1 reply; 89+ messages in thread From: J-P. Rosen @ 2018-04-16 8:32 UTC (permalink / raw) Le 16/04/2018 à 10:13, Dmitry A. Kazakov a écrit : > You would terminate descendants (grandchildren) from the rendezvous with > the child's Terminate: > > select > ... > or terminate > do -- Hidden rendezvous body > ... terminate all descendants > end Terminate; > else > ... spawn new descendants > end select; That's not what I mean. If you have both "terminate" and "select", if you select "terminate" (and all children are on a select with terminate), then you can terminate and you were right to select that branch. But if you select "else", then you can wake up other tasks that might in turn call your entries, so you were right not to select "terminate". That's what I call undecidable. >>> Anyway since T'Callable seems working, there is no need to use the >>> terminate alternative ever. >>> >> No, T'Callable becomes false AFTER the terminate has been selected. > > So GNAT implementation is wrong and this one is illegal? > > task body T is > begin > loop > exit when not T'Callable; > ... -- Do something > end loop; > end T; I don't know what Gnat is doing, but while T is normally active, T'Callable is True. This is clearly an infinite loop. -- J-P. Rosen Adalog 2 rue du Docteur Lombard, 92441 Issy-les-Moulineaux CEDEX Tel: +33 1 45 29 21 52, Fax: +33 1 45 29 25 00 http://www.adalog.fr ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: Finalization of library level tasks 2018-04-16 8:32 ` J-P. Rosen @ 2018-04-16 15:26 ` Dmitry A. Kazakov 2018-04-17 9:51 ` AdaMagica ` (2 more replies) 0 siblings, 3 replies; 89+ messages in thread From: Dmitry A. Kazakov @ 2018-04-16 15:26 UTC (permalink / raw) On 16/04/2018 10:32, J-P. Rosen wrote: > Le 16/04/2018 à 10:13, Dmitry A. Kazakov a écrit : >> You would terminate descendants (grandchildren) from the rendezvous with >> the child's Terminate: >> >> select >> ... >> or terminate >> do -- Hidden rendezvous body >> ... terminate all descendants >> end Terminate; >> else >> ... spawn new descendants >> end select; > That's not what I mean. If you have both "terminate" and "select", if > you select "terminate" (and all children are on a select with > terminate), then you can terminate and you were right to select that > branch. But if you select "else", then you can wake up other tasks that > might in turn call your entries, so you were right not to select > "terminate". That's what I call undecidable. OK, but why should I care? Once termination is engaged, the task must become not callable (which seems the case by GNAT) and any call from any child would fail, which should allow terminating them. >>>> Anyway since T'Callable seems working, there is no need to use the >>>> terminate alternative ever. >>>> >>> No, T'Callable becomes false AFTER the terminate has been selected. >> >> So GNAT implementation is wrong and this one is illegal? >> >> task body T is >> begin >> loop >> exit when not T'Callable; >> ... -- Do something >> end loop; >> end T; > I don't know what Gnat is doing, but while T is normally active, > T'Callable is True. This is clearly an infinite loop. It terminates under GNAT. Thus my question. The only place RM explains 'Callable is in ARM C.7.1:riddle: "(10.a.1/1):Ramification: {8652/0115} {AI95-00206-01} These routines can be called with an argument identifying the environment task. Is_Terminated will always be False for such a call, but Is_Callable (usually True) could be False if the environment task is waiting for the termination of dependent tasks. Thus, a dependent task can use Is_Callable to determine if the main subprogram has completed." At least for the environment task 'Callable is defined this (reasonable) way. It seems that GNAT uses this definition for all task. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: Finalization of library level tasks 2018-04-16 15:26 ` Dmitry A. Kazakov @ 2018-04-17 9:51 ` AdaMagica 2018-04-17 12:31 ` Dmitry A. Kazakov 2018-04-17 11:16 ` J-P. Rosen 2018-04-25 23:54 ` Randy Brukardt 2 siblings, 1 reply; 89+ messages in thread From: AdaMagica @ 2018-04-17 9:51 UTC (permalink / raw) Am Montag, 16. April 2018 17:26:42 UTC+2 schrieb Dmitry A. Kazakov: > >> So GNAT implementation is wrong and this one is illegal? > >> > >> task body T is > >> begin > >> loop > >> exit when not T'Callable; > >> ... -- Do something > >> end loop; > >> end T; > > I don't know what Gnat is doing, but while T is normally active, > > T'Callable is True. This is clearly an infinite loop. > > It terminates under GNAT. Thus my question. As I understand RM 9.3, when this task T is going out of scope, i.e. if it is declared inside for instance in a block, the block can only be left when the task is completed (the block is the master, see 7.6.1), and I cannot see that the conditions on T to be completed can ever be fulfilled for T. Thus the block cannot be left, the program is blocked. Gnat seems wrong to me. ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: Finalization of library level tasks 2018-04-17 9:51 ` AdaMagica @ 2018-04-17 12:31 ` Dmitry A. Kazakov 2018-04-17 15:37 ` Jeffrey R. Carter 2018-04-18 8:06 ` AdaMagica 0 siblings, 2 replies; 89+ messages in thread From: Dmitry A. Kazakov @ 2018-04-17 12:31 UTC (permalink / raw) On 17/04/2018 11:51, AdaMagica wrote: > Am Montag, 16. April 2018 17:26:42 UTC+2 schrieb Dmitry A. Kazakov: >>>> So GNAT implementation is wrong and this one is illegal? >>>> >>>> task body T is >>>> begin >>>> loop >>>> exit when not T'Callable; >>>> ... -- Do something >>>> end loop; >>>> end T; >>> I don't know what Gnat is doing, but while T is normally active, >>> T'Callable is True. This is clearly an infinite loop. >> >> It terminates under GNAT. Thus my question. > > As I understand RM 9.3, when this task T is going out of scope, i.e. if it is declared inside for instance in a block, the block can only be left when the task is completed (the block is the master, see 7.6.1), and I cannot see that the conditions on T to be completed can ever be fulfilled for T. Quite naturally, when the master is being finalized it marks the task as terminating and waits for its completion. The task marked for termination has T'Callable false and so terminates. > Thus the block cannot be left, the program is blocked. Gnat seems wrong to me. It would be an insane behavior. But that would not wonder me because rules are already insane, e.g. 7.6.1(4): "For the finalization of a master, dependent tasks are first awaited, as explained in 9.3. Then each object whose accessibility level is the same as that of the master is finalized if the object was successfully initialized and still exists." which is the reason why library-level task cannot be terminated using controlled objects. ------------------------------------------------------------ I thought about a method involving a helper task: Exiting : Boolean := False; type Exit_Event is new Ada.Finaization.Limited_Controlled with null record; procedure Finalize (X : in out Exit_Event) is begin Exiting := True; end Finalize; task Working_Around is entry Never_Entry; end Working_Around; task body Working_Around is X : Exit_Event; begin select accept Never_Entry; or terminate; end select; end Working; task body T is begin loop exit when not Exiting; ... -- Do something end loop; end T; I hoped that T'Callable, if defined meaningfully, could spare me this mess. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: Finalization of library level tasks 2018-04-17 12:31 ` Dmitry A. Kazakov @ 2018-04-17 15:37 ` Jeffrey R. Carter 2018-04-17 15:57 ` Dmitry A. Kazakov 2018-04-18 8:06 ` AdaMagica 1 sibling, 1 reply; 89+ messages in thread From: Jeffrey R. Carter @ 2018-04-17 15:37 UTC (permalink / raw) On 04/17/2018 02:31 PM, Dmitry A. Kazakov wrote: > > Quite naturally, when the master is being finalized it marks the task as > terminating and waits for its completion. The task marked for termination has > T'Callable false and so terminates. 'Callable returns True if the task is completed or abnormal. I would think that a task that can evaluate the condition of an "exit when" would be neither. > I hoped that T'Callable, if defined meaningfully, could spare me this mess. I'm pretty sure that Is_Callable (Environment_Task), as defined in the ARM, does what you want and spares you that mess. -- Jeff Carter "I was either in love, or I had smallpox." Take the Money and Run 137 ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: Finalization of library level tasks 2018-04-17 15:37 ` Jeffrey R. Carter @ 2018-04-17 15:57 ` Dmitry A. Kazakov 2018-04-17 20:16 ` Jeffrey R. Carter 2018-04-17 20:55 ` J-P. Rosen 0 siblings, 2 replies; 89+ messages in thread From: Dmitry A. Kazakov @ 2018-04-17 15:57 UTC (permalink / raw) On 2018-04-17 17:37, Jeffrey R. Carter wrote: > On 04/17/2018 02:31 PM, Dmitry A. Kazakov wrote: >> >> Quite naturally, when the master is being finalized it marks the task >> as terminating and waits for its completion. The task marked for >> termination has T'Callable false and so terminates. > > 'Callable returns True if the task is completed or abnormal. I would > think that a task that can evaluate the condition of an "exit when" > would be neither. Yet 'Callable is False when the environment task is neither completed not abnormal. The definition leaks. >> I hoped that T'Callable, if defined meaningfully, could spare me this >> mess. > > I'm pretty sure that Is_Callable (Environment_Task), as defined in the > ARM, does what you want and spares you that mess. What about this deduction: if the environment task is not callable then any other task is not callable, because it depends on the environment task. In that case any task allocated for a library level access type could use T'Callable (Is_Callable = 'Callable according to RM). Therefore GNAT is still correct. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: Finalization of library level tasks 2018-04-17 15:57 ` Dmitry A. Kazakov @ 2018-04-17 20:16 ` Jeffrey R. Carter 2018-04-17 20:59 ` Dmitry A. Kazakov 2018-04-17 20:55 ` J-P. Rosen 1 sibling, 1 reply; 89+ messages in thread From: Jeffrey R. Carter @ 2018-04-17 20:16 UTC (permalink / raw) On 04/17/2018 05:57 PM, Dmitry A. Kazakov wrote: > > What about this deduction: if the environment task is not callable then any > other task is not callable, because it depends on the environment task. That doesn't follow. There's nothing that prevents the environment task from being non-callable while other tasks are callable. When the environment task returns from calling the main-program subprogram, it becomes completed and non-callable. It then waits until all dependent tasks complete. Then it does library-level finalization. Then it terminates. There can be a period there when the environment task has completed and some dependent tasks have not. Indeed, if any library-level tasks never finish, that period can be infinite. -- Jeff Carter "I was either in love, or I had smallpox." Take the Money and Run 137 ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: Finalization of library level tasks 2018-04-17 20:16 ` Jeffrey R. Carter @ 2018-04-17 20:59 ` Dmitry A. Kazakov 2018-04-18 5:20 ` J-P. Rosen 0 siblings, 1 reply; 89+ messages in thread From: Dmitry A. Kazakov @ 2018-04-17 20:59 UTC (permalink / raw) On 2018-04-17 22:16, Jeffrey R. Carter wrote: > On 04/17/2018 05:57 PM, Dmitry A. Kazakov wrote: >> >> What about this deduction: if the environment task is not callable >> then any other task is not callable, because it depends on the >> environment task. > > That doesn't follow. There's nothing that prevents the environment task > from being non-callable while other tasks are callable. OK. If other things are inconsistent this one should be as well... At least I can hope that AdaCore will never fix this "bug" and the nonsense will not make it into the ACATS. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: Finalization of library level tasks 2018-04-17 20:59 ` Dmitry A. Kazakov @ 2018-04-18 5:20 ` J-P. Rosen 0 siblings, 0 replies; 89+ messages in thread From: J-P. Rosen @ 2018-04-18 5:20 UTC (permalink / raw) Le 17/04/2018 à 22:59, Dmitry A. Kazakov a écrit : > > At least I can hope that AdaCore will never fix this "bug" and the > nonsense will not make it into the ACATS. This is no nonsense, and there are lots of tests about termination in the ACATS. I can tell you: I wrote them. -- J-P. Rosen Adalog 2 rue du Docteur Lombard, 92441 Issy-les-Moulineaux CEDEX Tel: +33 1 45 29 21 52, Fax: +33 1 45 29 25 00 http://www.adalog.fr ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: Finalization of library level tasks 2018-04-17 15:57 ` Dmitry A. Kazakov 2018-04-17 20:16 ` Jeffrey R. Carter @ 2018-04-17 20:55 ` J-P. Rosen 2018-04-17 21:23 ` Dmitry A. Kazakov 1 sibling, 1 reply; 89+ messages in thread From: J-P. Rosen @ 2018-04-17 20:55 UTC (permalink / raw) Le 17/04/2018 à 17:57, Dmitry A. Kazakov a écrit : > Yet 'Callable is False when the environment task is neither completed > not abnormal. The definition leaks. This is wrong. Can you provide a complete example that shows that? Then I'll file a ticket to AdaCore -- J-P. Rosen Adalog 2 rue du Docteur Lombard, 92441 Issy-les-Moulineaux CEDEX Tel: +33 1 45 29 21 52, Fax: +33 1 45 29 25 00 http://www.adalog.fr ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: Finalization of library level tasks 2018-04-17 20:55 ` J-P. Rosen @ 2018-04-17 21:23 ` Dmitry A. Kazakov 2018-04-18 5:26 ` J-P. Rosen 0 siblings, 1 reply; 89+ messages in thread From: Dmitry A. Kazakov @ 2018-04-17 21:23 UTC (permalink / raw) On 2018-04-17 22:55, J-P. Rosen wrote: > Le 17/04/2018 à 17:57, Dmitry A. Kazakov a écrit : >> Yet 'Callable is False when the environment task is neither completed >> not abnormal. The definition leaks. ARM C.7.1(10): "The functions Is_Terminated and Is_Callable return the value of the corresponding attribute of the task identified by T. Ramification: {8652/0115} {AI95-00206-01} These routines can be called with an argument identifying the environment task. Is_Terminated will always be False for such a call, but Is_Callable (usually True) could be False if the environment task is waiting for the termination of dependent tasks. Thus, a dependent task can use Is_Callable to determine if the main subprogram has completed." > This is wrong. Can you provide a complete example that shows that? Then > I'll file a ticket to AdaCore No way! I want it working. (:-)) P.S. If "main subprogram complete" should mean "environment task complete" that is OK to me. However insane the wording sounds to me only the semantics counts. Why could not "task complete" mean "will select next terminate"? At least it would make some use out of having T'Callable. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: Finalization of library level tasks 2018-04-17 21:23 ` Dmitry A. Kazakov @ 2018-04-18 5:26 ` J-P. Rosen 2018-04-26 0:02 ` Randy Brukardt 0 siblings, 1 reply; 89+ messages in thread From: J-P. Rosen @ 2018-04-18 5:26 UTC (permalink / raw) Le 17/04/2018 à 23:23, Dmitry A. Kazakov a écrit : > P.S. If "main subprogram complete" should mean "environment task > complete" that is OK to me. However insane the wording sounds to me only > the semantics counts. The paragraph you quote says "has completed", not "complete". Remember, the main subprogram is called by the environment task. So, the main subprogram completes and exits, then the environment task waits for dependents, at which point its 'callable becomes false. > Why could not "task complete" mean "will select > next terminate"? At least it would make some use out of having T'Callable. 'Callable is very useful for regular tasks. Your quote suggests that there might also be some use for it on the environment task, which is not obvious. -- J-P. Rosen Adalog 2 rue du Docteur Lombard, 92441 Issy-les-Moulineaux CEDEX Tel: +33 1 45 29 21 52, Fax: +33 1 45 29 25 00 http://www.adalog.fr ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: Finalization of library level tasks 2018-04-18 5:26 ` J-P. Rosen @ 2018-04-26 0:02 ` Randy Brukardt 0 siblings, 0 replies; 89+ messages in thread From: Randy Brukardt @ 2018-04-26 0:02 UTC (permalink / raw) [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #1: Type: text/plain, Size: 1688 bytes --] "J-P. Rosen" <rosen@adalog.fr> wrote in message news:pb6kuf$jgl$1@gioia.aioe.org... > Le 17/04/2018 à 23:23, Dmitry A. Kazakov a écrit : >> P.S. If "main subprogram complete" should mean "environment task >> complete" that is OK to me. However insane the wording sounds to me only >> the semantics counts. > The paragraph you quote says "has completed", not "complete". Remember, > the main subprogram is called by the environment task. So, the main > subprogram completes and exits, then the environment task waits for > dependents, at which point its 'callable becomes false. > >> Why could not "task complete" mean "will select >> next terminate"? At least it would make some use out of having >> T'Callable. > 'Callable is very useful for regular tasks. Your quote suggests that > there might also be some use for it on the environment task, which is > not obvious. I invented that to get around Dmitry's original problem when I stumbled into it building Claw right after Ada 95 was finished. I was able to convince the ARG that the environment task ought to be completed once the main subprogram exits [that follows from the definition of the environment task], and that one should be able to use Ada.Task_Identification to query that. (You could do it even before the Environment_Task function, you just had to squirrel the environment task id during initial elaboration.) Several compilers didn't do this right, but one of the first things I added to the ACATS after taking over was a test of this case (once the ARG approved the idea, of course). So all modern compilers support the idiom of testing Callable of the environment task. Randy. ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: Finalization of library level tasks 2018-04-17 12:31 ` Dmitry A. Kazakov 2018-04-17 15:37 ` Jeffrey R. Carter @ 2018-04-18 8:06 ` AdaMagica 2018-04-18 8:25 ` Dmitry A. Kazakov 1 sibling, 1 reply; 89+ messages in thread From: AdaMagica @ 2018-04-18 8:06 UTC (permalink / raw) Am Dienstag, 17. April 2018 14:31:24 UTC+2 schrieb Dmitry A. Kazakov: > On 17/04/2018 11:51, AdaMagica wrote: >>>> task body T is >>>> begin >>>> loop >>>> exit when not T'Callable; >>>> ... -- Do something >>>> end loop; >>>> end T; > > As I understand RM 9.3, when this task T is going out of scope, i.e. if it is declared inside for instance in a block, the block can only be left when the task is completed (the block is the master, see 7.6.1), and I cannot see that the conditions on T to be completed can ever be fulfilled for T. > > Quite naturally, when the master is being finalized it marks the task as > terminating and waits for its completion. The task marked for > termination has T'Callable false and so terminates. Dmitry, please quote the RM where you can find this rule - I'm certain you will not find it. Your model of tasking in Ada is not completely in line with the RM. T'Callable is true as long as the T has not finished its body, and there is an infinite loop, so it cannot stop. > The meaning of > > select > terminate; > else > null; > end select; > > is crystal clear: continue if no master did request termination else > continue. Again, I thought that T'Callable were there to determine if a > master wants the task to terminate. RM is silent about that. Even for > the environment task it is in a side note. May be in your mind, but not in the RM. Your model is wrong. ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: Finalization of library level tasks 2018-04-18 8:06 ` AdaMagica @ 2018-04-18 8:25 ` Dmitry A. Kazakov 2018-04-18 8:52 ` Egil H H 0 siblings, 1 reply; 89+ messages in thread From: Dmitry A. Kazakov @ 2018-04-18 8:25 UTC (permalink / raw) On 18/04/2018 10:06, AdaMagica wrote: >> Quite naturally, when the master is being finalized it marks the task as >> terminating and waits for its completion. The task marked for >> termination has T'Callable false and so terminates. > > Dmitry, please quote the RM where you can find this rule - I'm certain you will not find it. It is not a rule, it is a possible implementation of finalization as defined in 7.6.1(4). Regarding the semantics of T'Callable, it is basically undefined except for the environment task, which implicitly defines otherwise undefined "completed" as "main completed" and that in turn implies Callable = False. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: Finalization of library level tasks 2018-04-18 8:25 ` Dmitry A. Kazakov @ 2018-04-18 8:52 ` Egil H H 2018-04-18 9:58 ` Dmitry A. Kazakov 0 siblings, 1 reply; 89+ messages in thread From: Egil H H @ 2018-04-18 8:52 UTC (permalink / raw) Undefined? 9.9(2), "a task is callable unless it is completed or abnormal" 9.3(5), "A task is said to be completed when the execution of its corresponding task_body is completed" ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: Finalization of library level tasks 2018-04-18 8:52 ` Egil H H @ 2018-04-18 9:58 ` Dmitry A. Kazakov 2018-04-18 11:33 ` J-P. Rosen 2018-04-26 0:04 ` Randy Brukardt 0 siblings, 2 replies; 89+ messages in thread From: Dmitry A. Kazakov @ 2018-04-18 9:58 UTC (permalink / raw) On 18/04/2018 10:52, Egil H H wrote: > Undefined? > > 9.9(2), "a task is callable unless it is completed or abnormal" > 9.3(5), "A task is said to be completed when the execution of its corresponding task_body is completed" OK, it is defined enough to confirm that T'Callable cannot be used to break finalization deadlock. If not at the library level then only way seems to be a helper task at the same level. After second thought no shared variable and a controlled object is needed in the helper task. The required construct: select terminate; -- Terminate if asked else null; end select; can be emulated using Callable on the helper task: task Helper is entry Never; end Helper; task body Helper is begin select accept Never; or terminate; end select; end Helper; task body Worker_Task is begin while Helper'Callable loop ... -- Do something end loop; end Worker_Task; When Helper and Worker_Task have same master then Worker_Task can break finalization deadlock by looking at the Helper. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: Finalization of library level tasks 2018-04-18 9:58 ` Dmitry A. Kazakov @ 2018-04-18 11:33 ` J-P. Rosen 2018-04-18 11:58 ` Dmitry A. Kazakov 2018-04-26 0:04 ` Randy Brukardt 1 sibling, 1 reply; 89+ messages in thread From: J-P. Rosen @ 2018-04-18 11:33 UTC (permalink / raw) Le 18/04/2018 à 11:58, Dmitry A. Kazakov a écrit : > can be emulated using Callable on the helper task: > > task Helper is > entry Never; > end Helper; > > task body Helper is > begin > select > accept Never; > or terminate; > end select; > end Helper; > > task body Worker_Task is > begin > while Helper'Callable loop > ... -- Do something > end loop; > end Worker_Task; > > When Helper and Worker_Task have same master then Worker_Task can break > finalization deadlock by looking at the Helper. Won't work. Please read 9.3(6/1): the open terminate_alternative is selected if and only if the following conditions are satisfied: - The task depends on some completed master; and - Each task that depends on the master considered is either already terminated or similarly blocked at a select_statement with an open terminate_alternative. Since Worker_Task and Helper depend on the same master, and Worker_Task is still busy, Helper won't select the terminate alternative, and will be still Callable. -- J-P. Rosen Adalog 2 rue du Docteur Lombard, 92441 Issy-les-Moulineaux CEDEX Tel: +33 1 45 29 21 52, Fax: +33 1 45 29 25 00 http://www.adalog.fr ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: Finalization of library level tasks 2018-04-18 11:33 ` J-P. Rosen @ 2018-04-18 11:58 ` Dmitry A. Kazakov 2018-04-18 12:00 ` J-P. Rosen 0 siblings, 1 reply; 89+ messages in thread From: Dmitry A. Kazakov @ 2018-04-18 11:58 UTC (permalink / raw) On 18/04/2018 13:33, J-P. Rosen wrote: > Le 18/04/2018 à 11:58, Dmitry A. Kazakov a écrit : >> can be emulated using Callable on the helper task: >> >> task Helper is >> entry Never; >> end Helper; >> >> task body Helper is >> begin >> select >> accept Never; >> or terminate; >> end select; >> end Helper; >> >> task body Worker_Task is >> begin >> while Helper'Callable loop >> ... -- Do something >> end loop; >> end Worker_Task; >> >> When Helper and Worker_Task have same master then Worker_Task can break >> finalization deadlock by looking at the Helper. > Won't work. Please read 9.3(6/1): > the open terminate_alternative is selected if and only if the following > conditions are satisfied: > - The task depends on some completed master; and > - Each task that depends on the master considered is either already > terminated or similarly blocked at a select_statement with an open > terminate_alternative. (plus a race condition in tow. One could construct a case when a couple of tasks will never terminate calling each other to ensure that at a time at least two of them do not offer terminate alternative. How nice) > Since Worker_Task and Helper depend on the same master, and Worker_Task > is still busy, Helper won't select the terminate alternative, and will > be still Callable. Well, it seems broken beyond repair then. Let me guess, there going to be no change to fix the mess. Right? -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: Finalization of library level tasks 2018-04-18 11:58 ` Dmitry A. Kazakov @ 2018-04-18 12:00 ` J-P. Rosen 2018-04-18 12:25 ` Dmitry A. Kazakov 0 siblings, 1 reply; 89+ messages in thread From: J-P. Rosen @ 2018-04-18 12:00 UTC (permalink / raw) Le 18/04/2018 à 13:58, Dmitry A. Kazakov a écrit : > Well, it seems broken beyond repair then. Let me guess, there going to > be no change to fix the mess. Right? No, since there is no mess, except in your expectations about what terminate means. It is intended to allow for clean termination of servers when no client is able to call them, and for that purpose, it works as intended. -- J-P. Rosen Adalog 2 rue du Docteur Lombard, 92441 Issy-les-Moulineaux CEDEX Tel: +33 1 45 29 21 52, Fax: +33 1 45 29 25 00 http://www.adalog.fr ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: Finalization of library level tasks 2018-04-18 12:00 ` J-P. Rosen @ 2018-04-18 12:25 ` Dmitry A. Kazakov 2018-04-18 13:51 ` J-P. Rosen 0 siblings, 1 reply; 89+ messages in thread From: Dmitry A. Kazakov @ 2018-04-18 12:25 UTC (permalink / raw) On 18/04/2018 14:00, J-P. Rosen wrote: > Le 18/04/2018 à 13:58, Dmitry A. Kazakov a écrit : >> Well, it seems broken beyond repair then. Let me guess, there going to >> be no change to fix the mess. Right? > No, since there is no mess, except in your expectations about what > terminate means. There is no any expectations, just an elementary requirement not to deadlock upon object finalization. > It is intended to allow for clean termination of servers when no client > is able to call them, and for that purpose, it works as intended. Sorry, but it does not work at all, because there is no any way to terminate task. If intended task termination has race condition, uses arbitrary dependencies between unrelated tasks, ignores stated dependencies, e.g. between the packages, deadlocks in finalization, then there must be something wrong with the intention. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: Finalization of library level tasks 2018-04-18 12:25 ` Dmitry A. Kazakov @ 2018-04-18 13:51 ` J-P. Rosen 2018-04-18 14:12 ` Dmitry A. Kazakov 0 siblings, 1 reply; 89+ messages in thread From: J-P. Rosen @ 2018-04-18 13:51 UTC (permalink / raw) Le 18/04/2018 à 14:25, Dmitry A. Kazakov a écrit : > Sorry, but it does not work at all, because there is no any way to > terminate task. If intended task termination has race condition, uses > arbitrary dependencies between unrelated tasks, ignores stated > dependencies, e.g. between the packages, deadlocks in finalization, then > there must be something wrong with the intention. It has not, or your termination conditions call for a higher protocol. All your suggestions are undecidable; please provide an example of the problem. -- J-P. Rosen Adalog 2 rue du Docteur Lombard, 92441 Issy-les-Moulineaux CEDEX Tel: +33 1 45 29 21 52, Fax: +33 1 45 29 25 00 http://www.adalog.fr ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: Finalization of library level tasks 2018-04-18 13:51 ` J-P. Rosen @ 2018-04-18 14:12 ` Dmitry A. Kazakov 2018-04-18 14:52 ` J-P. Rosen 0 siblings, 1 reply; 89+ messages in thread From: Dmitry A. Kazakov @ 2018-04-18 14:12 UTC (permalink / raw) On 18/04/2018 15:51, J-P. Rosen wrote: > Le 18/04/2018 à 14:25, Dmitry A. Kazakov a écrit : >> Sorry, but it does not work at all, because there is no any way to >> terminate task. If intended task termination has race condition, uses >> arbitrary dependencies between unrelated tasks, ignores stated >> dependencies, e.g. between the packages, deadlocks in finalization, then >> there must be something wrong with the intention. > It has not, or your termination conditions call for a higher protocol. > All your suggestions are undecidable; please provide an example of the > problem. Problem: A worker task encapsulated into an object. The task does some calculations or some I/O in chunks. The task's activity is not induced by other tasks. When the object finalizes the task must go with it. Nothing more. In pseudo-code: task body Worker is begin while the object lives loop do some chunk of work end loop; end Worker; P.S. I posted an example in a separate thread. The posted solution should work except the cases when the access type is at the same level as the object and both are below the library level. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: Finalization of library level tasks 2018-04-18 14:12 ` Dmitry A. Kazakov @ 2018-04-18 14:52 ` J-P. Rosen 2018-04-18 15:04 ` Dmitry A. Kazakov ` (2 more replies) 0 siblings, 3 replies; 89+ messages in thread From: J-P. Rosen @ 2018-04-18 14:52 UTC (permalink / raw) Le 18/04/2018 à 16:12, Dmitry A. Kazakov a écrit : > In pseudo-code: > > task body Worker is > begin > while the object lives loop > do some chunk of work > end loop; > end Worker; > > P.S. I posted an example in a separate thread. The posted solution > should work except the cases when the access type is at the same level > as the object and both are below the library level. > OK. You were actually quite close... Use a killer task (with the same master as your worker) like this: task Killer is entry Never_Called; end Killer; task body Killer is begin accept Never_Called; exception when Tasking_Error => -- Kill the other task end Killer; Hint: when the master completes, Tasking_Error is raised in all tasks waiting on entries that depend on that master. -- J-P. Rosen Adalog 2 rue du Docteur Lombard, 92441 Issy-les-Moulineaux CEDEX Tel: +33 1 45 29 21 52, Fax: +33 1 45 29 25 00 http://www.adalog.fr ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: Finalization of library level tasks 2018-04-18 14:52 ` J-P. Rosen @ 2018-04-18 15:04 ` Dmitry A. Kazakov 2018-04-18 20:26 ` AdaMagica 2018-04-18 20:40 ` AdaMagica 2018-04-18 21:29 ` J-P. Rosen 2 siblings, 1 reply; 89+ messages in thread From: Dmitry A. Kazakov @ 2018-04-18 15:04 UTC (permalink / raw) On 18/04/2018 16:52, J-P. Rosen wrote: > Le 18/04/2018 à 16:12, Dmitry A. Kazakov a écrit : >> In pseudo-code: >> >> task body Worker is >> begin >> while the object lives loop >> do some chunk of work >> end loop; >> end Worker; >> >> P.S. I posted an example in a separate thread. The posted solution >> should work except the cases when the access type is at the same level >> as the object and both are below the library level. >> > OK. You were actually quite close... Use a killer task (with the same > master as your worker) like this: > > task Killer is > entry Never_Called; > end Killer; > > task body Killer is > begin > accept Never_Called; > exception > when Tasking_Error => > -- Kill the other task > end Killer; > > Hint: when the master completes, Tasking_Error is raised in all tasks > waiting on entries that depend on that master. Does it raise for all entries? If it does no killer task is needed: task body Worker is begin loop begin select accept Never; else null; end select; exception when Tasking_Eror => exit; end; do some chunk of work end loop; end Worker; Should this work? -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: Finalization of library level tasks 2018-04-18 15:04 ` Dmitry A. Kazakov @ 2018-04-18 20:26 ` AdaMagica 2018-04-18 21:00 ` Dmitry A. Kazakov 0 siblings, 1 reply; 89+ messages in thread From: AdaMagica @ 2018-04-18 20:26 UTC (permalink / raw) Am Mittwoch, 18. April 2018 17:04:58 UTC+2 schrieb Dmitry A. Kazakov: > On 18/04/2018 16:52, J-P. Rosen wrote: > > Le 18/04/2018 à 16:12, Dmitry A. Kazakov a écrit : > >> In pseudo-code: > >> > >> task body Worker is > >> begin > >> while the object lives loop > >> do some chunk of work > >> end loop; > >> end Worker; > >> > >> P.S. I posted an example in a separate thread. The posted solution > >> should work except the cases when the access type is at the same level > >> as the object and both are below the library level. > >> > > OK. You were actually quite close... Use a killer task (with the same > > master as your worker) like this: > > > > task Killer is > > entry Never_Called; > > end Killer; > > > > task body Killer is > > begin > > accept Never_Called; > > exception > > when Tasking_Error => > > -- Kill the other task > > end Killer; > > > > Hint: when the master completes, Tasking_Error is raised in all tasks > > waiting on entries that depend on that master. > > Does it raise for all entries? If it does no killer task is needed: > > task body Worker is > begin > loop > begin > select > accept Never; > else > null; > end select; > exception > when Tasking_Eror => > exit; > end; > do some chunk of work > end loop; > end Worker; > > Should this work? No, because it's not waiting at the rendezvous. ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: Finalization of library level tasks 2018-04-18 20:26 ` AdaMagica @ 2018-04-18 21:00 ` Dmitry A. Kazakov 0 siblings, 0 replies; 89+ messages in thread From: Dmitry A. Kazakov @ 2018-04-18 21:00 UTC (permalink / raw) On 2018-04-18 22:26, AdaMagica wrote: > Am Mittwoch, 18. April 2018 17:04:58 UTC+2 schrieb Dmitry A. Kazakov: >> On 18/04/2018 16:52, J-P. Rosen wrote: >>> Le 18/04/2018 à 16:12, Dmitry A. Kazakov a écrit : >>>> In pseudo-code: >>>> >>>> task body Worker is >>>> begin >>>> while the object lives loop >>>> do some chunk of work >>>> end loop; >>>> end Worker; >>>> >>>> P.S. I posted an example in a separate thread. The posted solution >>>> should work except the cases when the access type is at the same level >>>> as the object and both are below the library level. >>>> >>> OK. You were actually quite close... Use a killer task (with the same >>> master as your worker) like this: >>> >>> task Killer is >>> entry Never_Called; >>> end Killer; >>> >>> task body Killer is >>> begin >>> accept Never_Called; >>> exception >>> when Tasking_Error => >>> -- Kill the other task >>> end Killer; >>> >>> Hint: when the master completes, Tasking_Error is raised in all tasks >>> waiting on entries that depend on that master. >> >> Does it raise for all entries? If it does no killer task is needed: >> >> task body Worker is >> begin >> loop >> begin >> select >> accept Never; >> else >> null; >> end select; >> exception >> when Tasking_Eror => >> exit; >> end; >> do some chunk of work >> end loop; >> end Worker; >> >> Should this work? > > No, because it's not waiting at the rendezvous. Strange semantics, at least. How about this: task body Worker is begin loop begin select accept Never; or delay 0.000_001; end select; exception when Tasking_Eror => exit; end; do some chunk of work end loop; end Worker; -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: Finalization of library level tasks 2018-04-18 14:52 ` J-P. Rosen 2018-04-18 15:04 ` Dmitry A. Kazakov @ 2018-04-18 20:40 ` AdaMagica 2018-04-19 7:34 ` Simon Wright 2018-04-18 21:29 ` J-P. Rosen 2 siblings, 1 reply; 89+ messages in thread From: AdaMagica @ 2018-04-18 20:40 UTC (permalink / raw) Am Mittwoch, 18. April 2018 16:52:04 UTC+2 schrieb J-P. Rosen: > Le 18/04/2018 à 16:12, Dmitry A. Kazakov a écrit : > > In pseudo-code: > > > > task body Worker is > > begin > > while the object lives loop > > do some chunk of work > > end loop; > > end Worker; > > > > P.S. I posted an example in a separate thread. The posted solution > > should work except the cases when the access type is at the same level > > as the object and both are below the library level. > > > OK. You were actually quite close... Use a killer task (with the same > master as your worker) like this: > > task Killer is > entry Never_Called; > end Killer; > > task body Killer is > begin > accept Never_Called; > exception > when Tasking_Error => > -- Kill the other task > end Killer; > > Hint: when the master completes, Tasking_Error is raised in all tasks > waiting on entries that depend on that master. I do not understand how this is supposed to work. ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: Finalization of library level tasks 2018-04-18 20:40 ` AdaMagica @ 2018-04-19 7:34 ` Simon Wright 0 siblings, 0 replies; 89+ messages in thread From: Simon Wright @ 2018-04-19 7:34 UTC (permalink / raw) AdaMagica <christ-usch.grein@t-online.de> writes: > Am Mittwoch, 18. April 2018 16:52:04 UTC+2 schrieb J-P. Rosen: >> OK. You were actually quite close... Use a killer task (with the same >> master as your worker) like this: >> >> task Killer is >> entry Never_Called; >> end Killer; >> >> task body Killer is >> begin >> accept Never_Called; >> exception >> when Tasking_Error => >> -- Kill the other task >> end Killer; >> >> Hint: when the master completes, Tasking_Error is raised in all tasks >> waiting on entries that depend on that master. > > I do not understand how this is supposed to work. I tried this: with Killer_Pack; procedure Killing is begin null; end Killing; package Killer_Pack is task Killer is entry Never_Called; end Killer; end Killer_Pack; with GNAT.IO; package body Killer_Pack is task body Killer is begin accept Never_Called; exception when Tasking_Error => GNAT.IO.Put_Line ("bye."); end Killer; end Killer_Pack; with all the GNATs I could lay my hands on (macOS) and they all hang: under gdb, (gdb) info tasks ID TID P-ID Pri State Name * 1 101000000 31 Child Termination Wait main_task 2 101000e00 1 31 Accept or Select Term killer Of course, I'm quite prepared to believe I've misunderstood the point. ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: Finalization of library level tasks 2018-04-18 14:52 ` J-P. Rosen 2018-04-18 15:04 ` Dmitry A. Kazakov 2018-04-18 20:40 ` AdaMagica @ 2018-04-18 21:29 ` J-P. Rosen 2018-04-19 7:32 ` Dmitry A. Kazakov 2 siblings, 1 reply; 89+ messages in thread From: J-P. Rosen @ 2018-04-18 21:29 UTC (permalink / raw) Le 18/04/2018 à 16:52, J-P. Rosen a écrit : > OK. You were actually quite close... Use a killer task (with the same > master as your worker) like this: > > task Killer is > entry Never_Called; > end Killer; > > task body Killer is > begin > accept Never_Called; > exception > when Tasking_Error => > -- Kill the other task > end Killer; > > Hint: when the master completes, Tasking_Error is raised in all tasks > waiting on entries that depend on that master. Sorry, my mistake. Typed too fast from an old trick I used... It's the other way round. When a task completes, it raises Tasking_Error in the tasks waiting on its entries. So, you can wait for the completion of a task without busy waiting by calling an entry of the task that is never accepted, and handling tasking_error. -- J-P. Rosen Adalog 2 rue du Docteur Lombard, 92441 Issy-les-Moulineaux CEDEX Tel: +33 1 45 29 21 52, Fax: +33 1 45 29 25 00 http://www.adalog.fr ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: Finalization of library level tasks 2018-04-18 21:29 ` J-P. Rosen @ 2018-04-19 7:32 ` Dmitry A. Kazakov 0 siblings, 0 replies; 89+ messages in thread From: Dmitry A. Kazakov @ 2018-04-19 7:32 UTC (permalink / raw) On 18/04/2018 23:29, J-P. Rosen wrote: > Le 18/04/2018 à 16:52, J-P. Rosen a écrit : >> OK. You were actually quite close... Use a killer task (with the same >> master as your worker) like this: >> >> task Killer is >> entry Never_Called; >> end Killer; >> >> task body Killer is >> begin >> accept Never_Called; >> exception >> when Tasking_Error => >> -- Kill the other task >> end Killer; >> >> Hint: when the master completes, Tasking_Error is raised in all tasks >> waiting on entries that depend on that master. > Sorry, my mistake. Typed too fast from an old trick I used... It's the > other way round. When a task completes, it raises Tasking_Error in the > tasks waiting on its entries. > > So, you can wait for the completion of a task without busy waiting by > calling an entry of the task that is never accepted, and handling > tasking_error. But how to complete that task in the first place? The scenario of task termination you described in this thread before specifically precludes any task to complete in the event of master waiting them to complete. It is a deadlock built into the language. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: Finalization of library level tasks 2018-04-18 9:58 ` Dmitry A. Kazakov 2018-04-18 11:33 ` J-P. Rosen @ 2018-04-26 0:04 ` Randy Brukardt 2018-04-26 8:56 ` Dmitry A. Kazakov 1 sibling, 1 reply; 89+ messages in thread From: Randy Brukardt @ 2018-04-26 0:04 UTC (permalink / raw) "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message news:pb74sr$1cmf$1@gioia.aioe.org... > On 18/04/2018 10:52, Egil H H wrote: >> Undefined? >> >> 9.9(2), "a task is callable unless it is completed or abnormal" >> 9.3(5), "A task is said to be completed when the execution of its >> corresponding task_body is completed" > > OK, it is defined enough to confirm that T'Callable cannot be used to > break finalization deadlock. Of course it can: you test T'Callable of your parent task, *not* of yourself. If that parent is the environment task, use the Task_Identification version. Randy. ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: Finalization of library level tasks 2018-04-26 0:04 ` Randy Brukardt @ 2018-04-26 8:56 ` Dmitry A. Kazakov 2018-04-26 22:10 ` Randy Brukardt 0 siblings, 1 reply; 89+ messages in thread From: Dmitry A. Kazakov @ 2018-04-26 8:56 UTC (permalink / raw) On 26/04/2018 02:04, Randy Brukardt wrote: > "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message > news:pb74sr$1cmf$1@gioia.aioe.org... >> On 18/04/2018 10:52, Egil H H wrote: >>> Undefined? >>> >>> 9.9(2), "a task is callable unless it is completed or abnormal" >>> 9.3(5), "A task is said to be completed when the execution of its >>> corresponding task_body is completed" >> >> OK, it is defined enough to confirm that T'Callable cannot be used to >> break finalization deadlock. > > Of course it can: you test T'Callable of your parent task, *not* of > yourself. If that parent is the environment task, use the > Task_Identification version. No, because the parent task is not going to terminate. The problem is to test if the current task is awaited to terminate in order to have an equivalent of: loop select terminate; else null; end select; -- Do a portion of work end loop; There is no solution to this below the library level where the environment task hack works. Under the library level an access to the task must be used *and* this pointer type must be declared one level up the future master of the task. I.e. it cannot be local in the scope where the object creating the task lives. This will deadlock as mandated by the RM. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: Finalization of library level tasks 2018-04-26 8:56 ` Dmitry A. Kazakov @ 2018-04-26 22:10 ` Randy Brukardt 2018-04-27 4:48 ` J-P. Rosen 0 siblings, 1 reply; 89+ messages in thread From: Randy Brukardt @ 2018-04-26 22:10 UTC (permalink / raw) "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message news:pbs473$co3$1@gioia.aioe.org... > On 26/04/2018 02:04, Randy Brukardt wrote: >> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message >> news:pb74sr$1cmf$1@gioia.aioe.org... >>> On 18/04/2018 10:52, Egil H H wrote: >>>> Undefined? >>>> >>>> 9.9(2), "a task is callable unless it is completed or abnormal" >>>> 9.3(5), "A task is said to be completed when the execution of its >>>> corresponding task_body is completed" >>> >>> OK, it is defined enough to confirm that T'Callable cannot be used to >>> break finalization deadlock. >> >> Of course it can: you test T'Callable of your parent task, *not* of >> yourself. If that parent is the environment task, use the >> Task_Identification version. > > No, because the parent task is not going to terminate. "completion" and "termination" are different concepts in Ada, and always have been. A completed task still has to await any tasks nested in it, and do finalization of any objects that it owns. So it still can execute code, make entry calls, and the like. > The problem is to test if the current task is awaited to terminate in > order to have an equivalent of: > > loop > select > terminate; > else > null; > end select; > -- Do a portion of work > end loop; The case I was considering is when the task is directly declared in another task. There is no mechanism to determine whether a task is awaited; I believe that would be a race condition and thus it was omitted from Ada. So if you declare a task in a block there is no practical way to terminate it -- ergo, don't do that. :-) > There is no solution to this below the library level where the environment > task hack works. It works fine if the task's master is another task, and it never works otherwise. It doesn't have anything specifically to do with the environment task -- you can do the same trick with any parent task. > Under the library level an access to the task must be used *and* this > pointer type must be declared one level up the future master of the task. > I.e. it cannot be local in the scope where the object creating the task > lives. This will deadlock as mandated by the RM. There's no problem if the task's master is that of the parent task, as I noted. One way to do that indeed is to use an access-to-task (but it doesn't have to be at library level). If you are looking for something more general, it doesn't exist. Randy. ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: Finalization of library level tasks 2018-04-26 22:10 ` Randy Brukardt @ 2018-04-27 4:48 ` J-P. Rosen 2018-04-27 20:52 ` Randy Brukardt 0 siblings, 1 reply; 89+ messages in thread From: J-P. Rosen @ 2018-04-27 4:48 UTC (permalink / raw) Le 27/04/2018 à 00:10, Randy Brukardt a écrit : > So if you declare a task in a block there is no practical way to terminate > it -- ergo, don't do that. :-) > Huh? Consider declare task Server is entry Service; end Server; task body Server is begin loop select accept Service do ... end Service; or terminate; end select; end loop; end Server; begin ... Server.Service; ... Server.Service; end; The task will terminate nicely when the block is completed. That's what terminate is for! -- J-P. Rosen Adalog 2 rue du Docteur Lombard, 92441 Issy-les-Moulineaux CEDEX Tel: +33 1 45 29 21 52, Fax: +33 1 45 29 25 00 http://www.adalog.fr ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: Finalization of library level tasks 2018-04-27 4:48 ` J-P. Rosen @ 2018-04-27 20:52 ` Randy Brukardt 0 siblings, 0 replies; 89+ messages in thread From: Randy Brukardt @ 2018-04-27 20:52 UTC (permalink / raw) [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #1: Type: text/plain, Size: 1057 bytes --] We were talking about the 90% of cases where "terminate" doesn't work, of course. Not the rare cases where it does. (I've never had one in the tasks I've written.) Randy. "J-P. Rosen" <rosen@adalog.fr> wrote in message news:pbua2d$1rt8$1@gioia.aioe.org... > Le 27/04/2018 à 00:10, Randy Brukardt a écrit : >> So if you declare a task in a block there is no practical way to >> terminate >> it -- ergo, don't do that. :-) >> > Huh? Consider > > declare > task Server is > entry Service; > end Server; > > task body Server is > begin > loop > select > accept Service do ... end Service; > or terminate; > end select; > end loop; > end Server; > begin > ... > Server.Service; > ... > Server.Service; > end; > > The task will terminate nicely when the block is completed. That's what > terminate is for! > > -- > J-P. Rosen > Adalog > 2 rue du Docteur Lombard, 92441 Issy-les-Moulineaux CEDEX > Tel: +33 1 45 29 21 52, Fax: +33 1 45 29 25 00 > http://www.adalog.fr ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: Finalization of library level tasks 2018-04-16 15:26 ` Dmitry A. Kazakov 2018-04-17 9:51 ` AdaMagica @ 2018-04-17 11:16 ` J-P. Rosen 2018-04-17 12:47 ` Dmitry A. Kazakov 2018-04-25 23:54 ` Randy Brukardt 2 siblings, 1 reply; 89+ messages in thread From: J-P. Rosen @ 2018-04-17 11:16 UTC (permalink / raw) Le 16/04/2018 à 17:26, Dmitry A. Kazakov a écrit : > The only place RM explains 'Callable is in ARM C.7.1:riddle: > > "(10.a.1/1):Ramification: {8652/0115} {AI95-00206-01} These routines can > be called with an argument identifying the environment task. > Is_Terminated will always be False for such a call, but Is_Callable > (usually True) could be False if the environment task is waiting for the > termination of dependent tasks. Thus, a dependent task can use > Is_Callable to determine if the main subprogram has completed." > > At least for the environment task 'Callable is defined this (reasonable) > way. It seems that GNAT uses this definition for all task. The environment task calls the main subprogram. Therefore, after the main subprogram has returned, the environment task may be waiting for other tasks to terminate, and is thus no more callable. But I don't see how this relates to your example. One thing to keep in mind is the meaning of "or terminate": it means that no task could possibly call an entry of the task, and therefore that the task is blocked forever. In this case, it is better to terminate it. If you had an else part, there is a way to revive it, and therefore it cannot be terminatable. -- J-P. Rosen Adalog 2 rue du Docteur Lombard, 92441 Issy-les-Moulineaux CEDEX Tel: +33 1 45 29 21 52, Fax: +33 1 45 29 25 00 http://www.adalog.fr ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: Finalization of library level tasks 2018-04-17 11:16 ` J-P. Rosen @ 2018-04-17 12:47 ` Dmitry A. Kazakov 2018-04-17 14:08 ` J-P. Rosen 0 siblings, 1 reply; 89+ messages in thread From: Dmitry A. Kazakov @ 2018-04-17 12:47 UTC (permalink / raw) On 17/04/2018 13:16, J-P. Rosen wrote: > Le 16/04/2018 à 17:26, Dmitry A. Kazakov a écrit : >> The only place RM explains 'Callable is in ARM C.7.1:riddle: >> >> "(10.a.1/1):Ramification: {8652/0115} {AI95-00206-01} These routines can >> be called with an argument identifying the environment task. >> Is_Terminated will always be False for such a call, but Is_Callable >> (usually True) could be False if the environment task is waiting for the >> termination of dependent tasks. Thus, a dependent task can use >> Is_Callable to determine if the main subprogram has completed." >> >> At least for the environment task 'Callable is defined this (reasonable) >> way. It seems that GNAT uses this definition for all task. > > The environment task calls the main subprogram. Therefore, after the > main subprogram has returned, the environment task may be waiting for > other tasks to terminate, and is thus no more callable. But I don't see > how this relates to your example. It is related directly. Environment_Task'Callable becomes False before completion when the task is still running. If 'Callable is same as 'Terminated why there are two of them? Anyway there must be a way to know if a task was requested to terminate, because the terminate alternative is useless for practical cases. > One thing to keep in mind is the meaning of "or terminate": it means > that no task could possibly call an entry of the task, and therefore > that the task is blocked forever. In this case, it is better to > terminate it. It is a circular statement. Yes, if you want to terminate a task you terminate it. You don't derive that from the task's state. That would be nonsense. If a task wants to terminate it does so without asking the master. If the master want to terminate a task it just orders this and waits. > If you had an else part, there is a way to revive it, and > therefore it cannot be terminatable. I don't understand the meaning of "revive". The meaning of select terminate; else null; end select; is crystal clear: continue if no master did request termination else continue. Again, I thought that T'Callable were there to determine if a master wants the task to terminate. RM is silent about that. Even for the environment task it is in a side note. I am puzzled. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: Finalization of library level tasks 2018-04-17 12:47 ` Dmitry A. Kazakov @ 2018-04-17 14:08 ` J-P. Rosen 2018-04-17 14:47 ` Dmitry A. Kazakov 0 siblings, 1 reply; 89+ messages in thread From: J-P. Rosen @ 2018-04-17 14:08 UTC (permalink / raw) Le 17/04/2018 à 14:47, Dmitry A. Kazakov a écrit : > I don't understand the meaning of "revive". The meaning of > > select > terminate; > else > null; > end select; > > is crystal clear: continue if no master did request termination else > continue. Again, I thought that T'Callable were there to determine if a > master wants the task to terminate. It's just that your mental model of 'Callable and Terminate is not the one of Ada. A master does not require termination from its dependent tasks: it checks (recursively) if all the dependent tasks are either already terminated or similarly waiting on a select-with-terminate. If yes, the whole family terminates simultaneously. When a master is waiting for dependent tasks to terminate (at its end, NOT if on a select-with-terminate), it is not yet Terminated, but it is no more Callable. -- J-P. Rosen Adalog 2 rue du Docteur Lombard, 92441 Issy-les-Moulineaux CEDEX Tel: +33 1 45 29 21 52, Fax: +33 1 45 29 25 00 http://www.adalog.fr ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: Finalization of library level tasks 2018-04-17 14:08 ` J-P. Rosen @ 2018-04-17 14:47 ` Dmitry A. Kazakov 2018-04-17 22:00 ` Robert A Duff 0 siblings, 1 reply; 89+ messages in thread From: Dmitry A. Kazakov @ 2018-04-17 14:47 UTC (permalink / raw) On 17/04/2018 16:08, J-P. Rosen wrote: > Le 17/04/2018 à 14:47, Dmitry A. Kazakov a écrit : >> I don't understand the meaning of "revive". The meaning of >> >> select >> terminate; >> else >> null; >> end select; >> >> is crystal clear: continue if no master did request termination else >> continue. Again, I thought that T'Callable were there to determine if a >> master wants the task to terminate. > It's just that your mental model of 'Callable and Terminate is not the > one of Ada. A master does not require termination from its dependent > tasks: it checks (recursively) if all the dependent tasks are either > already terminated or similarly waiting on a select-with-terminate. If > yes, the whole family terminates simultaneously. That simply cannot work. The task (or task manager) must know if the terminate alternative can be selected. That depends on the master's state. Master or something on its behalf must tell the task that it must start selecting terminate alternatives. > When a master is waiting for dependent tasks to terminate (at its end, > NOT if on a select-with-terminate), it is not yet Terminated, but it is > no more Callable. In that case task body T is begin while T'Callable loop ... end loop; end T; must work, GNAT is correct, I am happy. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: Finalization of library level tasks 2018-04-17 14:47 ` Dmitry A. Kazakov @ 2018-04-17 22:00 ` Robert A Duff 2018-04-18 7:25 ` Dmitry A. Kazakov 0 siblings, 1 reply; 89+ messages in thread From: Robert A Duff @ 2018-04-17 22:00 UTC (permalink / raw) "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes: > task body T is > begin > while T'Callable loop > ... > end loop; > end T; > > must work, GNAT is correct, I am happy. I'm not sure what you mean by "work". GNAT correctly compiles that into an infinite loop, as J-P explained. Here's a complete example: with Text_IO; use Text_IO; package Foo is task T; end Foo; package body Foo is task body T is begin while T'Callable loop Put_Line("Hello"); delay 2.0; end loop; end T; end Foo; procedure Foo.Main is begin null; end Foo.Main; This prints "Hello" every 2 seconds until you get bored and kill it. I think perhaps you wanted to query Callable on the environment task, not T. If so, please post a complete example, and say what GNAT is doing, and why you think that's wrong (or right?). - Bob ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: Finalization of library level tasks 2018-04-17 22:00 ` Robert A Duff @ 2018-04-18 7:25 ` Dmitry A. Kazakov 0 siblings, 0 replies; 89+ messages in thread From: Dmitry A. Kazakov @ 2018-04-18 7:25 UTC (permalink / raw) On 18/04/2018 00:00, Robert A Duff wrote: > "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes: > >> task body T is >> begin >> while T'Callable loop >> ... >> end loop; >> end T; >> >> must work, GNAT is correct, I am happy. > > I'm not sure what you mean by "work". GNAT correctly > compiles that into an infinite loop, as J-P explained. > Here's a complete example: > > with Text_IO; use Text_IO; > package Foo is > task T; > end Foo; > > package body Foo is > task body T is > begin > while T'Callable loop > Put_Line("Hello"); > delay 2.0; > end loop; > end T; > end Foo; > > procedure Foo.Main is > begin > null; > end Foo.Main; > > This prints "Hello" every 2 seconds until you get > bored and kill it. In my case it ends. So it is "fixed", unfortunately. It was not that useful anyway because it would not work for nested tasks which have exactly same problem in the case when the master is at the same level. It is not so notorious because programmers tend to allocate tasks dynamically and declare the corresponding pointer at the library level. So the finalization deadlock does not happen. > I think perhaps you wanted to query Callable on the environment > task, not T. If so, please post a complete example, and say > what GNAT is doing, and why you think that's wrong (or right?). I will post an example to augment encapsulated task pattern in order to work around language idiosyncrasies. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: Finalization of library level tasks 2018-04-16 15:26 ` Dmitry A. Kazakov 2018-04-17 9:51 ` AdaMagica 2018-04-17 11:16 ` J-P. Rosen @ 2018-04-25 23:54 ` Randy Brukardt 2018-04-26 16:22 ` Jeffrey R. Carter 2 siblings, 1 reply; 89+ messages in thread From: Randy Brukardt @ 2018-04-25 23:54 UTC (permalink / raw) "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message news:pb2fbf$516$1@gioia.aioe.org... > It terminates under GNAT. Thus my question. > > The only place RM explains 'Callable is in ARM C.7.1:riddle: Interesting. It should be declared somewhere. Anyway, the rule is that T'Callable = True unless the task is completed. See 9.3 for the definition of completed. If the task is still running, it can't be completed, so T'Callable has to be true. The code you have is an infinite loop. It should be using the parent task (whatever that is) as the prefix of the attribute. Randy. ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: Finalization of library level tasks 2018-04-25 23:54 ` Randy Brukardt @ 2018-04-26 16:22 ` Jeffrey R. Carter 2018-04-26 16:43 ` Dmitry A. Kazakov 0 siblings, 1 reply; 89+ messages in thread From: Jeffrey R. Carter @ 2018-04-26 16:22 UTC (permalink / raw) On 04/26/2018 01:54 AM, Randy Brukardt wrote: > "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message >> >> The only place RM explains 'Callable is in ARM C.7.1:riddle: > > Interesting. It should be declared somewhere. Anyway, the rule is that > T'Callable = True unless the task is completed. See 9.3 for the definition > of completed. 'Callable and the concept of "callable" are defined at ARM 9.9(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." -- Jeff Carter "Every sperm is sacred." Monty Python's the Meaning of Life 55 ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: Finalization of library level tasks 2018-04-26 16:22 ` Jeffrey R. Carter @ 2018-04-26 16:43 ` Dmitry A. Kazakov 2018-04-26 20:19 ` J-P. Rosen 0 siblings, 1 reply; 89+ messages in thread From: Dmitry A. Kazakov @ 2018-04-26 16:43 UTC (permalink / raw) On 2018-04-26 18:22, Jeffrey R. Carter wrote: > On 04/26/2018 01:54 AM, Randy Brukardt wrote: >> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message >>> >>> The only place RM explains 'Callable is in ARM C.7.1:riddle: >> >> Interesting. It should be declared somewhere. Anyway, the rule is that >> T'Callable = True unless the task is completed. See 9.3 for the >> definition >> of completed. > > 'Callable and the concept of "callable" are defined at ARM 9.9(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." Literally it means "can be called". In task body T is begin select accept X; or terminate; end select; end T; X cannot be called when the master awaits termination of T. Thus *logically* T is not callable when terminate will be selected. Surely there could be another attribute with a different name, or a predefined entry to be accepted when the master is waiting. Or both. Among with finalization deadlock another problem of terminate alternative is that there is not rendezvous. Surely programmers wish do be able to do explicit cleanup on termination without misusing controlled objects: select ... or terminate do ... -- Complete task end terminate; end select; [ Yes, we want to be able to requeue terminate and to make entry calls from there. ] -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: Finalization of library level tasks 2018-04-26 16:43 ` Dmitry A. Kazakov @ 2018-04-26 20:19 ` J-P. Rosen 0 siblings, 0 replies; 89+ messages in thread From: J-P. Rosen @ 2018-04-26 20:19 UTC (permalink / raw) Le 26/04/2018 à 18:43, Dmitry A. Kazakov a écrit : > Literally it means "can be called". In > > task body T is > begin > select > accept X; > or terminate; > end select; > end T; > > X cannot be called when the master awaits termination of T. Thus > *logically* T is not callable when terminate will be selected. Wrong. X can be called by other subtasks of the same master that are still active (that's why the master is completed but not terminated). -- J-P. Rosen Adalog 2 rue du Docteur Lombard, 92441 Issy-les-Moulineaux CEDEX Tel: +33 1 45 29 21 52, Fax: +33 1 45 29 25 00 http://www.adalog.fr ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: Finalization of library level tasks 2018-04-15 17:40 ` Dmitry A. Kazakov 2018-04-15 19:32 ` Egil H H 2018-04-16 5:19 ` J-P. Rosen @ 2018-04-16 9:19 ` AdaMagica 2018-04-16 15:15 ` Dmitry A. Kazakov 2 siblings, 1 reply; 89+ messages in thread From: AdaMagica @ 2018-04-16 9:19 UTC (permalink / raw) Am Sonntag, 15. April 2018 19:40:38 UTC+2 schrieb Dmitry A. Kazakov: > On 2018-04-15 19:17, AdaMagica wrote: > > task body Worker_Type is > > begin > > loop > > select > > accept Quit; > > exit; > > or > > terminate; > > end select; > > end loop; > > end Worker_Type; > > > > procedure Finalize (X: in out T) is > > begin > > if X.Worker'Callable then > > X.Worker.Quit; > > end if; > > end Finalize; > > This task will hang in the select statement. > > Terminate alternative is almost always useless because it cannot be > mixed with "else" or "delay". The only way to request the completion from outside a task is (if I remember correctly) an abort statement. Then you don't need terminate. Terminate is designed for passive tasks (let's call them thus), which become active only on request, i.e. via an entry call. Thus terminate, delay and else-statement are mutually exclusive. (I'm sure you know all this well.) Terminate is called by (hm, dunno, a task supervisor) when it is clear that there are no more clients who can call any of the entries, so the task has nothing more to do. A delay or else-statement would be a contradiction. Thus your design seems wrong if you need something like this. > If there were a way to check within the > task if its completion has been requested your solution would work. > Terminate should have been a normal predefined entry: > > task body T is > begin > select > accept T'Terminate; > exit; > or ... This would lead to a very different tasking feature - a completely different Ada you every now and then seem to propose. ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: Finalization of library level tasks 2018-04-16 9:19 ` AdaMagica @ 2018-04-16 15:15 ` Dmitry A. Kazakov 0 siblings, 0 replies; 89+ messages in thread From: Dmitry A. Kazakov @ 2018-04-16 15:15 UTC (permalink / raw) On 16/04/2018 11:19, AdaMagica wrote: > Terminate is called by (hm, dunno, a task supervisor) when it is clear that there are no more clients who can call any of the entries, so the task has nothing more to do. A delay or else-statement would be a contradiction. When the task goes out of scope you cannot continue without terminating the task. > Thus your design seems wrong if you need something like this. > >> If there were a way to check within the >> task if its completion has been requested your solution would work. >> Terminate should have been a normal predefined entry: >> >> task body T is >> begin >> select >> accept T'Terminate; >> exit; >> or ... > > This would lead to a very different tasking feature - a completely different Ada you every now and then seem to propose. I don't know how this is that much different. You cannot terminate task unconditionally or instantly because local object must be finalized on the context of the task. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: Finalization of library level tasks 2018-04-15 15:46 ` AdaMagica 2018-04-15 15:53 ` Dmitry A. Kazakov 2018-04-15 17:17 ` AdaMagica @ 2018-04-19 20:39 ` G. B. 2018-04-20 7:27 ` Dmitry A. Kazakov 2 siblings, 1 reply; 89+ messages in thread From: G. B. @ 2018-04-19 20:39 UTC (permalink / raw) AdaMagica <christ-usch.grein@t-online.de> wrote: > Am Sonntag, 15. April 2018 17:15:22 UTC+2 schrieb Dmitry A. Kazakov: >> e.g. fooling the accessibility rules of the access type, some sort of >> Unchecked_Allocation. Ada 83 had pragma Controlled to require the >> compiler to keep its hands off, alas, it was removed. > > This pragma was never implemented by any compiler (because there never > was a garbage collector implemented and the pragma was intended to tell > the GC to keep its hand off). > Both AdaMagic and GNAT can compile for the JVM. GNAT also targets .NET. These are GC targets. It’s not big business, seemingly, but then what is. ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: Finalization of library level tasks 2018-04-19 20:39 ` G. B. @ 2018-04-20 7:27 ` Dmitry A. Kazakov 0 siblings, 0 replies; 89+ messages in thread From: Dmitry A. Kazakov @ 2018-04-20 7:27 UTC (permalink / raw) On 19/04/2018 22:39, G. B. wrote: > AdaMagica <christ-usch.grein@t-online.de> wrote: >> Am Sonntag, 15. April 2018 17:15:22 UTC+2 schrieb Dmitry A. Kazakov: >>> e.g. fooling the accessibility rules of the access type, some sort of >>> Unchecked_Allocation. Ada 83 had pragma Controlled to require the >>> compiler to keep its hands off, alas, it was removed. >> >> This pragma was never implemented by any compiler (because there never >> was a garbage collector implemented and the pragma was intended to tell >> the GC to keep its hand off). > > Both AdaMagic and GNAT can compile for the JVM. > GNAT also targets .NET. These are GC targets. > It’s not big business, seemingly, but then what is. GC is not the point. The point is to be able to turn off any stuff Ada implicitly does for finalization and completion of objects allocated using allocator of the specified access type: 1. Remove from the list of objects to be finalized 2. From the list of storage [sub]pool objects 3. From the list of objects allocated using a local access type 4. Ignore any rules about task masters If you were to build your custom GC you might probably wish this option too. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: Finalization of library level tasks 2018-04-15 15:15 ` Dmitry A. Kazakov 2018-04-15 15:46 ` AdaMagica @ 2018-04-25 23:46 ` Randy Brukardt 2018-04-26 9:03 ` Dmitry A. Kazakov 1 sibling, 1 reply; 89+ messages in thread From: Randy Brukardt @ 2018-04-25 23:46 UTC (permalink / raw) "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message news:pavqa6$1qdj$1@gioia.aioe.org... ... > Yes. The problem is the order of finalization. For some unclear reason the > task's access type is attempted before the object that contains that > access type because they are in the same scope. It's not unclear - tasks have to terminate before objects are finalized so that the tasks aren't trying to use finalized objects. If the object is a protected object, that could be a really bad deal (remember that finalizing a protected object raises tasking error in any queued task and prevents future calls). We ran into this with Claw, and eventually had the Ada.Task_Identification solution ingrained into the Standard. (I believe you found it from some other messages that I saw previously, so I won't describe it here.) Randy. ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: Finalization of library level tasks 2018-04-25 23:46 ` Randy Brukardt @ 2018-04-26 9:03 ` Dmitry A. Kazakov 2018-04-26 22:25 ` Randy Brukardt 0 siblings, 1 reply; 89+ messages in thread From: Dmitry A. Kazakov @ 2018-04-26 9:03 UTC (permalink / raw) On 26/04/2018 01:46, Randy Brukardt wrote: > "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message > news:pavqa6$1qdj$1@gioia.aioe.org... > ... >> Yes. The problem is the order of finalization. For some unclear reason the >> task's access type is attempted before the object that contains that >> access type because they are in the same scope. > > It's not unclear - tasks have to terminate before objects are finalized so > that the tasks aren't trying to use finalized objects. If the object is a > protected object, that could be a really bad deal (remember that finalizing > a protected object raises tasking error in any queued task and prevents > future calls). It is all objects, not just ones containing the task. You could have: package A is task type Foo ... X : Foo; end A; package A.B is type Bar is new Ada.Finalization.Controlled ... Y : Bar; end A.B; Even so, finalization of Y will await termination of X! The deadlock in the RM is constructed to prevent any possible way to break it. There are dozens ways to fix the mess but there seems no interest at all. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: Finalization of library level tasks 2018-04-26 9:03 ` Dmitry A. Kazakov @ 2018-04-26 22:25 ` Randy Brukardt 2018-04-27 7:37 ` Dmitry A. Kazakov 0 siblings, 1 reply; 89+ messages in thread From: Randy Brukardt @ 2018-04-26 22:25 UTC (permalink / raw) "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message news:pbs4km$doq$1@gioia.aioe.org... > On 26/04/2018 01:46, Randy Brukardt wrote: >> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message >> news:pavqa6$1qdj$1@gioia.aioe.org... >> ... >>> Yes. The problem is the order of finalization. For some unclear reason >>> the >>> task's access type is attempted before the object that contains that >>> access type because they are in the same scope. >> >> It's not unclear - tasks have to terminate before objects are finalized >> so >> that the tasks aren't trying to use finalized objects. If the object is a >> protected object, that could be a really bad deal (remember that >> finalizing >> a protected object raises tasking error in any queued task and prevents >> future calls). > > It is all objects, not just ones containing the task. You could have: > > package A is > task type Foo ... > X : Foo; > end A; > > package A.B is > type Bar is new Ada.Finalization.Controlled ... > Y : Bar; > end A.B; > > Even so, finalization of Y will await termination of X! It has to. There is no way for the compiler to know that there is no way for X to access Y. > The deadlock in the RM is constructed to prevent any possible way to break > it. Correct, and that is by design. An unbreakable premise of Ada is that finalization of objects will always be done no matter what happens. That's why subpools have a finalization mechanism, Unchecked_Deallocation does finalization, assignment does finalization, ad nauseum. The designer of an Ada library (ADT) can always be assured that their last wishes will be executed regardless of what horrors the client tries to invent. This is a critical property for reusability. > There are dozens ways to fix the mess but there seems no interest at all. Correction: there are dozens of ways to make a worse mess. There is no way to "fix" the issue, because any change to the rules just breaks in some other case. Or completely destroys the ability of ADTs to assume that finalization happens. When we ran into the problem in the Claw design, I spent a lot of time trying to come up with a fix. I couldn't find anything that didn't have worse problems in some cases. I believe other ARG members did the same thing; the environment task solution seemed to be the best workaround (it works great in Claw, presuming of course that the compiler implements it correctly). Claw, for instance, uses a number of locks. We had problems with compilers finalizing those locks before awaiting tasks, meaning that the tasks got Program_Error for no expected reason. (And one compiler that will remain nameless just crashed if you called such a lock; there's an ACATS test for that, too, these days.) The critical thing from an Ada perspective is that the rules are well-defined and don't change from implementation-to-implementation. Then it is always possible to find a solution (not necessarily an easy one). Task termination is rarely considered in Ada books, yet it is one of the hardest things to accomplish. I don't have any termination technique at all in the spam filter, because I couldn't think of anything that would actually work. Luckily, you can just kill the process from Windows in the few cases where you need to shut the thing down. One of the advantages of the parallelism model in Ada 2020 is that you don't have to write explicit tasks so you don't have to deal with termination of them. Randy. ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: Finalization of library level tasks 2018-04-26 22:25 ` Randy Brukardt @ 2018-04-27 7:37 ` Dmitry A. Kazakov 2018-04-27 8:32 ` AdaMagica 2018-04-27 21:08 ` Randy Brukardt 0 siblings, 2 replies; 89+ messages in thread From: Dmitry A. Kazakov @ 2018-04-27 7:37 UTC (permalink / raw) On 27/04/2018 00:25, Randy Brukardt wrote: > "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message > news:pbs4km$doq$1@gioia.aioe.org... >> On 26/04/2018 01:46, Randy Brukardt wrote: >>> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message >>> news:pavqa6$1qdj$1@gioia.aioe.org... >>> ... >>>> Yes. The problem is the order of finalization. For some unclear reason >>>> the >>>> task's access type is attempted before the object that contains that >>>> access type because they are in the same scope. >>> >>> It's not unclear - tasks have to terminate before objects are finalized >>> so >>> that the tasks aren't trying to use finalized objects. If the object is a >>> protected object, that could be a really bad deal (remember that >>> finalizing >>> a protected object raises tasking error in any queued task and prevents >>> future calls). >> >> It is all objects, not just ones containing the task. You could have: >> >> package A is >> task type Foo ... >> X : Foo; >> end A; >> >> package A.B is >> type Bar is new Ada.Finalization.Controlled ... >> Y : Bar; >> end A.B; >> >> Even so, finalization of Y will await termination of X! > > It has to. There is no way for the compiler to know that there is no way for > X to access Y. > >> The deadlock in the RM is constructed to prevent any possible way to break >> it. > > Correct, and that is by design. An unbreakable premise of Ada is that > finalization of objects will always be done no matter what happens. That's > why subpools have a finalization mechanism, Unchecked_Deallocation does > finalization, assignment does finalization, ad nauseum. The designer of an > Ada library (ADT) can always be assured that their last wishes will be > executed regardless of what horrors the client tries to invent. This is a > critical property for reusability. It is not reusable when the code depends on whether the object is declared at the library level or not. It is not reusable when pointers are unavoidable. It is not reusable when the "standard" task termination method is not usable and must be always replaced with some kludge to be reinvented each time new. >> There are dozens ways to fix the mess but there seems no interest at all. > > Correction: there are dozens of ways to make a worse mess. There is no way > to "fix" the issue, because any change to the rules just breaks in some > other case. Or completely destroys the ability of ADTs to assume that > finalization happens. Nothing will be broken by adding a Boolean attribute T'Completion_Awaited. Nothing will be broken by fixing the finalization model that does not distinguish finalization of the class from finalization of the type-specific object. You *can* finalize the class of the object containing the task with the task component still running: type Container_Type is .. tagged ... T : Task_Type; The order of finalization must be: Finalize Container_Type'Class; Stop T; -- Existing order Finalize Container_Type; Finalize T; Note that Ada 95 type system wisely distinguished Container_Type'Class and Container_Type, while finalization inconsistently ignores the difference. Nothing will be broken by adding user-controlled aspect to access type to kill any bookkeeping, any hidden lists, any dependencies. [...] > One of the advantages of the parallelism model in Ada 2020 is that you don't > have to write explicit tasks so you don't have to deal with termination of > them. I don't see how this will help with designing active objects, writing servers for I/O protocols, handling pools of worker tasks. If ARG wants get rid of explicit tasks it should seriously revise the type system. The task type must be an interface to derive from. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: Finalization of library level tasks 2018-04-27 7:37 ` Dmitry A. Kazakov @ 2018-04-27 8:32 ` AdaMagica 2018-04-27 8:57 ` Dmitry A. Kazakov 2018-04-27 21:08 ` Randy Brukardt 1 sibling, 1 reply; 89+ messages in thread From: AdaMagica @ 2018-04-27 8:32 UTC (permalink / raw) Am Freitag, 27. April 2018 09:37:46 UTC+2 schrieb Dmitry A. Kazakov: > You *can* finalize the class of the object containing the task with the > task component still running: > > type Container_Type is .. tagged ... > T : Task_Type; > > The order of finalization must be: > > Finalize Container_Type'Class; > Stop T; -- Existing order IIUC, you mean the task T is stopped anywhere in the middle of its work? Ada calls this abort. This means a lot of things may be left in an invalid state. Normal task completion takes place at defined places, everything is left in a well-defined state. It's your design work to define those places. > Finalize Container_Type; > Finalize T; > > Note that Ada 95 type system wisely distinguished Container_Type'Class ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: Finalization of library level tasks 2018-04-27 8:32 ` AdaMagica @ 2018-04-27 8:57 ` Dmitry A. Kazakov 0 siblings, 0 replies; 89+ messages in thread From: Dmitry A. Kazakov @ 2018-04-27 8:57 UTC (permalink / raw) On 27/04/2018 10:32, AdaMagica wrote: > Am Freitag, 27. April 2018 09:37:46 UTC+2 schrieb Dmitry A. Kazakov: >> You *can* finalize the class of the object containing the task with the >> task component still running: >> >> type Container_Type is .. tagged ... >> T : Task_Type; >> >> The order of finalization must be: >> >> Finalize Container_Type'Class; >> Stop T; -- Existing order > > IIUC, you mean the task T is stopped anywhere in the middle of its work? No, I mean that the task is awaited, e.g. to accept terminate. What I meant is that finalization of a class object does not need to wait for the task to end. Therefore from the class' Finalize you could ask the task to stop: task type Task_Type is entry Shutdown; end Task_Type; type Container_Type is new Ada.Finalization.Limited_Controlled with record T : Task_Type; end record; procedure Finalize (Object : in out Container_Type'Class); for Container_Type'Class'Finalize use Finalize ; -- Whatever syntax procedure Finalize (Object : in out Container_Type'Class) is begin Object.T.Shutdown; -- You cannot do that from normal Finalize, end Finalize; -- it is too late then Presently class finalization is null. BTW, after class finalization dispatching calls on the class must result in an exception. It should have been a bounded error to dispatch from Initialize or Finalize. One of the inconsistencies of controlled types design is that dispatching is allowed in Finalization <=> the class considered operational, but task components are not running <=> the class considered non-operational. Either one or another. > Ada calls this abort. This means a lot of things may be left in an invalid state. Yes. Task abort is almost never usable. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: Finalization of library level tasks 2018-04-27 7:37 ` Dmitry A. Kazakov 2018-04-27 8:32 ` AdaMagica @ 2018-04-27 21:08 ` Randy Brukardt 2018-04-28 8:35 ` Dmitry A. Kazakov 1 sibling, 1 reply; 89+ messages in thread From: Randy Brukardt @ 2018-04-27 21:08 UTC (permalink / raw) "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message news:pbuk07$9mf$1@gioia.aioe.org... ... > It is not reusable when the code depends on whether the object is declared > at the library level or not. That only happens if you write broken code in the first place: tasks should never be embedded in objects. It simply doesn't work (Ichbiah got that wrong). When you do so, termination is a problem, but so is avoiding deadlocks, race conditions, and the like. The entire nesting model of tasks in Ada is huge overkill and should never have happened - it's a huge amount of complexity for a value approaching zero. (Note that the first thing Ravenscar discards is the nesting model.) >>> There are dozens ways to fix the mess but there seems no interest at >>> all. >> >> Correction: there are dozens of ways to make a worse mess. There is no >> way >> to "fix" the issue, because any change to the rules just breaks in some >> other case. Or completely destroys the ability of ADTs to assume that >> finalization happens. > > Nothing will be broken by adding a Boolean attribute T'Completion_Awaited. I've been told that would lead people to writing code which depends on race conditions. I'm not enough of an expert on tasking to try to disagree with people that are. > Nothing will be broken by fixing the finalization model that does not > distinguish finalization of the class from finalization of the > type-specific object. A class is purely a static construct (just like privacy), while finalization is a purely dynamic construct. There's nothing to "distinguish" -- at runtime, all objects have a specific type. Finalization of a "class" can do nothing, as there is nothing dynamically to do with classes. ... > Nothing will be broken by adding user-controlled aspect to access type to > kill any bookkeeping, any hidden lists, any dependencies. Of course, the invariant that finalization always happens would be broken. That's a dead body issue with me, as it would destroy the ability to write reusable libraries. Note that as with memory allocation, a well-designed reusable library needs to be agnostic as to how clients use it in tasks. It should work properly when used sequentially, with multiple tasks, with parallel blocks/loops, and anything yet to be invented. That means nothing active should be in the library anymore than that the library should be allocating any memory. ... > I don't see how this will help with designing active objects, writing > servers for I/O protocols, handling pools of worker tasks. IMHO, active objects are evil. Use something like Parafin for pools for worker tasks (or just a parallel loop with the task checking turned off). "terminate" works fine for most servers, that's what it was designed for. And both pools and servers are always going to be at library level, so the workarounds can be used if "terminate" doesn't work. Randy. ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: Finalization of library level tasks 2018-04-27 21:08 ` Randy Brukardt @ 2018-04-28 8:35 ` Dmitry A. Kazakov 2018-04-29 17:41 ` AdaMagica 2018-05-01 2:27 ` Randy Brukardt 0 siblings, 2 replies; 89+ messages in thread From: Dmitry A. Kazakov @ 2018-04-28 8:35 UTC (permalink / raw) On 2018-04-27 23:08, Randy Brukardt wrote: > "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message > news:pbuk07$9mf$1@gioia.aioe.org... > ... >> It is not reusable when the code depends on whether the object is declared >> at the library level or not. > > That only happens if you write broken code in the first place: tasks should > never be embedded in objects. You argued for reusable code and ended up with claiming encapsulation broken? > It simply doesn't work (Ichbiah got that > wrong). When you do so, termination is a problem, but so is avoiding > deadlocks, race conditions, and the like. These are imposed by the language not by the program logic. > The entire nesting model of tasks > in Ada is huge overkill and should never have happened - it's a huge amount > of complexity for a value approaching zero. (Note that the first thing > Ravenscar discards is the nesting model.) while Ravescar itself is discarded by most applications. >>>> There are dozens ways to fix the mess but there seems no interest at >>>> all. >>> >>> Correction: there are dozens of ways to make a worse mess. There is no >>> way >>> to "fix" the issue, because any change to the rules just breaks in some >>> other case. Or completely destroys the ability of ADTs to assume that >>> finalization happens. >> >> Nothing will be broken by adding a Boolean attribute T'Completion_Awaited. > > I've been told that would lead people to writing code which depends on race > conditions. I'm not enough of an expert on tasking to try to disagree with > people that are. Better that code than no code at all. Presently no functional code can be written. In order to make an argument people who told you that must present a working code without alleged "race conditions". There is none, so the argument is void. >> Nothing will be broken by fixing the finalization model that does not >> distinguish finalization of the class from finalization of the >> type-specific object. > > A class is purely a static construct (just like privacy), while finalization > is a purely dynamic construct. There's nothing to "distinguish" -- at > runtime, all objects have a specific type. Yes, but is irrelevant to the lifetime of the said objects. I am talking about objects [containing tasks]. > Finalization of a "class" can do > nothing, as there is nothing dynamically to do with classes. It is not finalization of the class of types, it is finalization of an instance of a class-wide object. Each object of a tagged type is an instance of this type, and per language design that allows views, an instance of *all* ancestor types. Per same design, it is also an instance of all class-wide types rooted in the said types. All these instances *must* be finalized: X of T1 <- T2 <- T3 must be finalized in the order Finalize (T1'Class (X)); Finalize (T2'Class (X)); Finalize (T3'Class (X)); Finalize (T3 (X)); -- Only this is actually done Finalize (T2 (X)); -- These are left for the user Finalize (T1 (X)); > ... >> Nothing will be broken by adding user-controlled aspect to access type to >> kill any bookkeeping, any hidden lists, any dependencies. > > Of course, the invariant that finalization always happens would be broken. > That's a dead body issue with me, as it would destroy the ability to write > reusable libraries. No, it will only allow that. The same effect is customary achieved by declaring all access types at the library level. That makes the code more re-usable because it eliminates harmful checks. Pointers are too hot for any language to handle. Just leave them be and allow the programmer to do things right. > Note that as with memory allocation, a well-designed reusable library needs > to be agnostic as to how clients use it in tasks. It should work properly > when used sequentially, with multiple tasks, with parallel blocks/loops, and > anything yet to be invented. That means nothing active should be in the > library anymore than that the library should be allocating any memory. Just my point. If anybody knows how to make it working then the programmer. > ... >> I don't see how this will help with designing active objects, writing >> servers for I/O protocols, handling pools of worker tasks. > > IMHO, active objects are evil. Use something like Parafin for pools for > worker tasks (or just a parallel loop with the task checking turned off). > "terminate" works fine for most servers, that's what it was designed for. Unless you need start and stop servers on demand. > And both pools and servers are always going to be at library level, so the > workarounds can be used if "terminate" doesn't work. No, because servers are parts of the components that come and go. You are thinking about some sort of monolithic application which is a use case taking less and less percentage. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: Finalization of library level tasks 2018-04-28 8:35 ` Dmitry A. Kazakov @ 2018-04-29 17:41 ` AdaMagica 2018-04-29 19:36 ` Dmitry A. Kazakov 2018-05-01 2:27 ` Randy Brukardt 1 sibling, 1 reply; 89+ messages in thread From: AdaMagica @ 2018-04-29 17:41 UTC (permalink / raw) Am Samstag, 28. April 2018 10:35:34 UTC+2 schrieb Dmitry A. Kazakov: > All these instances *must* be finalized: X of T1 <- T2 <- T3 must be > finalized in the order > > Finalize (T1'Class (X)); > Finalize (T2'Class (X)); > Finalize (T3'Class (X)); I don't have the slightest idea what should happen there. > Finalize (T3 (X)); -- Only this is actually done Yes, this might be forgotten: > Finalize (T2 (X)); -- These are left for the user > Finalize (T1 (X)); ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: Finalization of library level tasks 2018-04-29 17:41 ` AdaMagica @ 2018-04-29 19:36 ` Dmitry A. Kazakov 2018-04-30 12:27 ` AdaMagica 0 siblings, 1 reply; 89+ messages in thread From: Dmitry A. Kazakov @ 2018-04-29 19:36 UTC (permalink / raw) On 2018-04-29 19:41, AdaMagica wrote: > Am Samstag, 28. April 2018 10:35:34 UTC+2 schrieb Dmitry A. Kazakov: > >> All these instances *must* be finalized: X of T1 <- T2 <- T3 must be >> finalized in the order >> >> Finalize (T1'Class (X)); >> Finalize (T2'Class (X)); >> Finalize (T3'Class (X)); > I don't have the slightest idea what should happen there. Anything necessary to finalize the class-wide object. E.g. informing a task component to complete: type T1; task type Worker_Type (Parent : not null access T1'Class) is entry Shutdown; end Worker_Type; type T1 is new Ada.Finalization.Limited_Controlled with record Worker : Worker_Type; end record; procedure Finalize (Object : in out T1'Class) is begin Object.Worker.Shutdown; end Finalize; Differently to type-specific Finalize in a class-wide Finalize it is OK to make dispatching calls. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: Finalization of library level tasks 2018-04-29 19:36 ` Dmitry A. Kazakov @ 2018-04-30 12:27 ` AdaMagica 2018-04-30 13:03 ` Dmitry A. Kazakov 2018-04-30 16:52 ` Jeffrey R. Carter 0 siblings, 2 replies; 89+ messages in thread From: AdaMagica @ 2018-04-30 12:27 UTC (permalink / raw) Am Sonntag, 29. April 2018 21:36:37 UTC+2 schrieb Dmitry A. Kazakov: > On 2018-04-29 19:41, AdaMagica wrote: > > Am Samstag, 28. April 2018 10:35:34 UTC+2 schrieb Dmitry A. Kazakov: > > > >> All these instances *must* be finalized: X of T1 <- T2 <- T3 must be > >> finalized in the order > >> > >> Finalize (T1'Class (X)); > >> Finalize (T2'Class (X)); > >> Finalize (T3'Class (X)); > > I don't have the slightest idea what should happen there. > > Anything necessary to finalize the class-wide object. E.g. informing a > task component to complete: What is this "anything"? I do not see a connection from class-wide type to its task components. What is the connection of class-wide type to other components? What's the difference between task components and other (perhaps limited) components? What does class-wide finalize do to those other components? In short: If you look inside a class-wide object, you'll find inside an object of a specific type within this class (as Randy said in a previous post). What's the property of this specific object seen as a class-wide object that's not a property of the specific object? (I have problems expressing what I want to say.I > type T1; > task type Worker_Type (Parent : not null access T1'Class) is > entry Shutdown; > end Worker_Type; > type T1 is new Ada.Finalization.Limited_Controlled with record > Worker : Worker_Type; > end record; > > procedure Finalize (Object : in out T1'Class) is > begin > Object.Worker.Shutdown; > end Finalize; > > Differently to type-specific Finalize in a class-wide Finalize it is OK > to make dispatching calls. ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: Finalization of library level tasks 2018-04-30 12:27 ` AdaMagica @ 2018-04-30 13:03 ` Dmitry A. Kazakov 2018-04-30 16:52 ` Jeffrey R. Carter 1 sibling, 0 replies; 89+ messages in thread From: Dmitry A. Kazakov @ 2018-04-30 13:03 UTC (permalink / raw) On 2018-04-30 14:27, AdaMagica wrote: > Am Sonntag, 29. April 2018 21:36:37 UTC+2 schrieb Dmitry A. Kazakov: >> On 2018-04-29 19:41, AdaMagica wrote: >>> Am Samstag, 28. April 2018 10:35:34 UTC+2 schrieb Dmitry A. Kazakov: >>> >>>> All these instances *must* be finalized: X of T1 <- T2 <- T3 must be >>>> finalized in the order >>>> >>>> Finalize (T1'Class (X)); >>>> Finalize (T2'Class (X)); >>>> Finalize (T3'Class (X)); >>> I don't have the slightest idea what should happen there. >> >> Anything necessary to finalize the class-wide object. E.g. informing a >> task component to complete: > > What is this "anything"? Anything the program logic requires for a class-wide finalization to be done. > I do not see a connection from class-wide type to its task components. What is the connection of class-wide type to other components? What's the difference between task components and other (perhaps limited) components? What does class-wide finalize do to those other components? The reason why the object's type-specific finalization waits for all component tasks to complete do not apply to class-wide finalization of the same object. When you have a task component with a Rosen's trick access discriminant T1'Class in the object of T1, without waiting for the task, you may finalize T3 and T2 and have the task running with a T1'Class object partially finalized. This is why the task must complete *before* finalization of T1, T2, T3 etc. There is no problem not to wait for the task during finalization of T1'Class because at this point T1, T2, T3 views of the object are all intact. You can safely dispatch on the task discriminant to any target type. From T1'Class finalization will shutdown the task and everything will be fine, deadlock broken. Similarly. Let the design require calling an abstract or overridden operation upon finalization via dispatch. You cannot do that in the Finalize of T1. The reason is exactly same as with the task completion: the object is partially finalized in the type T3 where dispatch may lead to. But you can safely dispatch in the Finalize of T1'Class, because T3 view is still there. > In short: If you look inside a class-wide object, you'll find inside an object of a specific type within this class (as Randy said in a previous post). What's the property of this specific object seen as a class-wide object that's not a property of the specific object? Simple. All properties of the class, overridden operations, in particular. Primitive operations dispatch on a class-wide object, they do not on a type-specific object. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: Finalization of library level tasks 2018-04-30 12:27 ` AdaMagica 2018-04-30 13:03 ` Dmitry A. Kazakov @ 2018-04-30 16:52 ` Jeffrey R. Carter 2018-04-30 17:06 ` Dmitry A. Kazakov 2018-05-01 9:17 ` AdaMagica 1 sibling, 2 replies; 89+ messages in thread From: Jeffrey R. Carter @ 2018-04-30 16:52 UTC (permalink / raw) On 04/30/2018 02:27 PM, AdaMagica wrote: > > In short: If you look inside a class-wide object, you'll find inside an object of a specific type within this class (as Randy said in a previous post). What's the property of this specific object seen as a class-wide object that's not a property of the specific object? About the only difference is that operations dispatch with a class-wide parameter and don't with a parameter of a specific type. Op (Parent'Class (X) ); and Op (X); end up executing the same code. That Kazakov says they don't is probably an indication that he, as he often does, is not talking about Ada. -- Jeff Carter "You couldn't catch clap in a brothel, silly English K...niggets." Monty Python & the Holy Grail 19 ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: Finalization of library level tasks 2018-04-30 16:52 ` Jeffrey R. Carter @ 2018-04-30 17:06 ` Dmitry A. Kazakov 2018-05-01 9:17 ` AdaMagica 1 sibling, 0 replies; 89+ messages in thread From: Dmitry A. Kazakov @ 2018-04-30 17:06 UTC (permalink / raw) On 2018-04-30 18:52, Jeffrey R. Carter wrote: > On 04/30/2018 02:27 PM, AdaMagica wrote: >> >> In short: If you look inside a class-wide object, you'll find inside >> an object of a specific type within this class (as Randy said in a >> previous post). What's the property of this specific object seen as a >> class-wide object that's not a property of the specific object? > > About the only difference is that operations dispatch with a class-wide > parameter and don't with a parameter of a specific type. > > Op (Parent'Class (X) ); > > and > > Op (X); > > end up executing the same code. Wrong. Consider this: type T1 is tagged null record; procedure Op (X : in out T1); type T2 is new T1 with null record; procedure Op (X : in out T2); type T3 is new T2 with null record; procedure Op (X : in out T3); Now this procedure: procedure Finalize (X : in out T2); if you pass T3 to it then procedure Finalize (X : in out T2) is begin Op (T1'Class (X)); -- Dispatches to Op (T3 (X)) Op (X); -- Statically calls to Op (T2 (X)) The code is not same because dispatch can cross the actual type border and go a descendant. This is also why dispatching in Finalize should have been illegal. All re-dispatch should have been illegal because it breaks typing. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: Finalization of library level tasks 2018-04-30 16:52 ` Jeffrey R. Carter 2018-04-30 17:06 ` Dmitry A. Kazakov @ 2018-05-01 9:17 ` AdaMagica 2018-05-01 9:40 ` Dmitry A. Kazakov 2018-05-01 11:18 ` Jeffrey R. Carter 1 sibling, 2 replies; 89+ messages in thread From: AdaMagica @ 2018-05-01 9:17 UTC (permalink / raw) Am Montag, 30. April 2018 18:52:21 UTC+2 schrieb Jeffrey R. Carter: > On 04/30/2018 02:27 PM, AdaMagica wrote: > > > > In short: If you look inside a class-wide object, you'll find inside an object of a specific type within this class (as Randy said in a previous post). What's the property of this specific object seen as a class-wide object that's not a property of the specific object? > > About the only difference is that operations dispatch with a class-wide > parameter and don't with a parameter of a specific type. > > Op (Parent'Class (X) ); > > and > > Op (X); > > end up executing the same code. That Kazakov says they don't is probably an > indication that he, as he often does, is not talking about Ada. Of course he's not talking about current Ada, he's talking about an Ada as he would like her to be as there is no Finalize'Class he would like to have. But he is correct on this example you gave: With redispatch, OP(X) and OP(Parent'Class(X)) are not the same. What I do not understand is the model he wants to have for Finalize'Class. The idea is quite complicated because of Rosen's trick, redispatch etc. Dmitry only posts some fragmentary ideas without ever giving a complete elaboration. So we, if we try to understand and argue with him, have to imagine and guess what the hell he has in mind. As in this (incomplete) post of his: > Now this procedure: > procedure Finalize (X : in out T2); > if you pass T3 to it then You cannot directly pass an x of type T3 to this Finalize. You can make his example work if you add quite some more code. His examples like this one, if really current Ada (and not some wishful version), are rarely complete. ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: Finalization of library level tasks 2018-05-01 9:17 ` AdaMagica @ 2018-05-01 9:40 ` Dmitry A. Kazakov 2018-05-01 11:18 ` Jeffrey R. Carter 1 sibling, 0 replies; 89+ messages in thread From: Dmitry A. Kazakov @ 2018-05-01 9:40 UTC (permalink / raw) On 2018-05-01 11:17, AdaMagica wrote: > What I do not understand is the model he wants to have for Finalize'Class. I can elaborate if you explain what you understand under "model". > The idea is quite complicated because of Rosen's trick, redispatch etc. No, the idea is simple - objects of any type must allow user-defined finalization (and initialization). Rosen's trick and re-dispatch are not my ideas but existing Ada features. The latter has huge issues with type consistency which has negative effect on finalization. > Dmitry only posts some fragmentary ideas without ever giving a complete elaboration. So we, if we try to understand and argue with him, have to imagine and guess what the hell he has in mind. I am ready to answer any questions. Normally all discussions deviate straight to "Aber, meine Herren, das ist keine Physik", or to denial of any software design concepts from ADT to nested tasks and then the problem itself: nobody needs X (substitute "finalization", "task component" etc). > You cannot directly pass an x of type T3 to this Finalize. You can make his example work if you add quite some more code. His examples like this one, if really current Ada (and not some wishful version), are rarely complete. Yes, it is always pseudo-code I use in such discussions. If I made it precise, people would critique syntax issues. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: Finalization of library level tasks 2018-05-01 9:17 ` AdaMagica 2018-05-01 9:40 ` Dmitry A. Kazakov @ 2018-05-01 11:18 ` Jeffrey R. Carter 2018-05-01 11:27 ` Dmitry A. Kazakov 2018-05-01 15:54 ` Niklas Holsti 1 sibling, 2 replies; 89+ messages in thread From: Jeffrey R. Carter @ 2018-05-01 11:18 UTC (permalink / raw) On 05/01/2018 11:17 AM, AdaMagica wrote: > > But he is correct on this example you gave: With redispatch, OP(X) and OP(Parent'Class(X)) are not the same. If you use redispatching then you get what you deserve. -- Jeff Carter "My little plum, I am like Robin Hood. I take from the rich, and I give to the poor. ... Us poor." Poppy 96 ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: Finalization of library level tasks 2018-05-01 11:18 ` Jeffrey R. Carter @ 2018-05-01 11:27 ` Dmitry A. Kazakov 2018-05-01 15:54 ` Niklas Holsti 1 sibling, 0 replies; 89+ messages in thread From: Dmitry A. Kazakov @ 2018-05-01 11:27 UTC (permalink / raw) On 2018-05-01 13:18, Jeffrey R. Carter wrote: > On 05/01/2018 11:17 AM, AdaMagica wrote: >> >> But he is correct on this example you gave: With redispatch, OP(X) and >> OP(Parent'Class(X)) are not the same. > > If you use redispatching then you get what you deserve. The first step in understanding the importance of having class-wide finalization and initialization ... -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: Finalization of library level tasks 2018-05-01 11:18 ` Jeffrey R. Carter 2018-05-01 11:27 ` Dmitry A. Kazakov @ 2018-05-01 15:54 ` Niklas Holsti 2018-05-02 14:34 ` AdaMagica 1 sibling, 1 reply; 89+ messages in thread From: Niklas Holsti @ 2018-05-01 15:54 UTC (permalink / raw) On 18-05-01 14:18 , Jeffrey R. Carter wrote: > On 05/01/2018 11:17 AM, AdaMagica wrote: >> >> But he is correct on this example you gave: With redispatch, OP(X) and >> OP(Parent'Class(X)) are not the same. > > If you use redispatching then you get what you deserve. Which can be exactly what you want to achieve! (Obligatory dissenting voice in favour of occasional redispatching, to avoid the appearance that redispatching is universally abhorred.) -- Niklas Holsti Tidorum Ltd niklas holsti tidorum fi . @ . ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: Finalization of library level tasks 2018-05-01 15:54 ` Niklas Holsti @ 2018-05-02 14:34 ` AdaMagica 2018-05-02 14:50 ` Dmitry A. Kazakov 0 siblings, 1 reply; 89+ messages in thread From: AdaMagica @ 2018-05-02 14:34 UTC (permalink / raw) Am Dienstag, 1. Mai 2018 17:54:02 UTC+2 schrieb Niklas Holsti: > On 18-05-01 14:18 , Jeffrey R. Carter wrote: > > On 05/01/2018 11:17 AM, AdaMagica wrote: > >> > >> But he is correct on this example you gave: With redispatch, OP(X) and > >> OP(Parent'Class(X)) are not the same. > > > > If you use redispatching then you get what you deserve. > > Which can be exactly what you want to achieve! > > (Obligatory dissenting voice in favour of occasional redispatching, to > avoid the appearance that redispatching is universally abhorred.) Yes, there are situations where redispatching is essential. I've once come into this situation. But I would say, do not use redispatch in Initialize, Adjust, Finalize. This is strong advice. Think thrice if you think you need it. ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: Finalization of library level tasks 2018-05-02 14:34 ` AdaMagica @ 2018-05-02 14:50 ` Dmitry A. Kazakov 0 siblings, 0 replies; 89+ messages in thread From: Dmitry A. Kazakov @ 2018-05-02 14:50 UTC (permalink / raw) On 02/05/2018 16:34, AdaMagica wrote: > Am Dienstag, 1. Mai 2018 17:54:02 UTC+2 schrieb Niklas Holsti: >> On 18-05-01 14:18 , Jeffrey R. Carter wrote: >>> On 05/01/2018 11:17 AM, AdaMagica wrote: >>>> >>>> But he is correct on this example you gave: With redispatch, OP(X) and >>>> OP(Parent'Class(X)) are not the same. >>> >>> If you use redispatching then you get what you deserve. >> >> Which can be exactly what you want to achieve! >> >> (Obligatory dissenting voice in favour of occasional redispatching, to >> avoid the appearance that redispatching is universally abhorred.) > > Yes, there are situations where redispatching is essential. I've once come into this situation. They are all wrong, either due to design error or language problem. In particular in Ada there is no partial override. Usually re-dispatch is required because there no way to define a prologue or epilogue of a primitive operation. So if you have this: procedure Foo (X : in out T) is begin ... Do this Baz (T'Class (X)); ... Do that end Foo; That is the language problem which does not allow T to define Foo's prologue and epilogue not to be overridden: procedure Foo'Prologue (X : in out T) is begin ... Do this end Foo'Prologue; procedure Foo (X : in out T) is null; procedure Foo'Epilogue (X : in out T) is begin ... Do that end Foo'Epilogue; Then Baz would be a plain overriding of Foo, no re-dispatch. BTW, Finalize must have been an epilogue, and Initialize a prologue. > But I would say, do not use redispatch in Initialize, Adjust, Finalize. This is strong advice. Think thrice if you think you need it. It is always wrong to dispatch from Initialize and Finalize, no need to even think about it. As I said before it must be plain dispatch from class-wide Finalize/Initialize/Adjust when all type-specific Finalizes are complete and Initializes not yet called. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: Finalization of library level tasks 2018-04-28 8:35 ` Dmitry A. Kazakov 2018-04-29 17:41 ` AdaMagica @ 2018-05-01 2:27 ` Randy Brukardt 2018-05-01 6:59 ` Dmitry A. Kazakov 1 sibling, 1 reply; 89+ messages in thread From: Randy Brukardt @ 2018-05-01 2:27 UTC (permalink / raw) "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message news:pc1bok$iqf$1@gioia.aioe.org... > On 2018-04-27 23:08, Randy Brukardt wrote: >> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message >> news:pbuk07$9mf$1@gioia.aioe.org... >> ... >>> It is not reusable when the code depends on whether the object is >>> declared >>> at the library level or not. >> >> That only happens if you write broken code in the first place: tasks >> should >> never be embedded in objects. > > You argued for reusable code and ended up with claiming encapsulation > broken? Encapusulation of threads is a nonsense idea. Encapsulation is a compile-time concept that completely disappears at runtime. A thread (a task or tasklet) is a run-time entity with little compile-time presence. Trying to encapsulate that makes about as much sense as trying to hide memory allocation (which also doesn't really work). In today's environment, one has to keep the threads at the highest possible level of a program, otherwise you will drown in overhead. Sticking threads inside of things is exactly opposed to that. I expect that in a future environment, threads will be assigned by the compiler, and again writing them explicitly is opposed to that. (And if you're not concerned about performance, please don't use them at all - the disadvantages outweight any possible advantages.) I don't see a reasonable scenario where hiding threads is ever going to be a good idea. It might work on some compilation system, but it will never be that portable. Randy. ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: Finalization of library level tasks 2018-05-01 2:27 ` Randy Brukardt @ 2018-05-01 6:59 ` Dmitry A. Kazakov 0 siblings, 0 replies; 89+ messages in thread From: Dmitry A. Kazakov @ 2018-05-01 6:59 UTC (permalink / raw) On 2018-05-01 04:27, Randy Brukardt wrote: > "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message > news:pc1bok$iqf$1@gioia.aioe.org... >> On 2018-04-27 23:08, Randy Brukardt wrote: >>> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message >>> news:pbuk07$9mf$1@gioia.aioe.org... >>> ... >>>> It is not reusable when the code depends on whether the object is >>>> declared >>>> at the library level or not. >>> >>> That only happens if you write broken code in the first place: tasks >>> should >>> never be embedded in objects. >> >> You argued for reusable code and ended up with claiming encapsulation >> broken? > > Encapusulation of threads is a nonsense idea. Encapsulation is a > compile-time concept that completely disappears at runtime. So is the data type and many other things. It is called abstraction, which you want to throw overboard together with encapsulation. > A thread (a task > or tasklet) is a run-time entity with little compile-time presence. Trying > to encapsulate that makes about as much sense as trying to hide memory > allocation (which also doesn't really work). Hiding memory allocation works perfectly well. Ada is a proof of that. I can return String from a subprogram. > In today's environment, one has to keep the threads at the highest possible > level of a program, otherwise you will drown in overhead. No. It is a perverse design with exposes implementation. There is no reason for the user of a complex communication object to know how many OS threads the thing uses. > Sticking threads > inside of things is exactly opposed to that. I expect that in a future > environment, threads will be assigned by the compiler, and again writing > them explicitly is opposed to that. (And if you're not concerned about > performance, please don't use them at all - the disadvantages outweight any > possible advantages.) I don't see a reasonable scenario where hiding threads > is ever going to be a good idea. It might work on some compilation system, > but it will never be that portable. It is 100% portable, our middleware which is 100% Ada runs under Windows, Linux, VxWorks and exposes no threads to the user. Why should he ever know which threads are used by an EtherCAT master, by CANOpen master, by MODBUS client etc? -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 89+ messages in thread
end of thread, other threads:[~2018-05-02 14:50 UTC | newest] Thread overview: 89+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2018-04-15 13:40 Finalization of library level tasks Dmitry A. Kazakov 2018-04-15 14:02 ` Jeffrey R. Carter 2018-04-15 14:12 ` Dmitry A. Kazakov 2018-04-15 14:54 ` Jeffrey R. Carter 2018-04-15 15:15 ` Dmitry A. Kazakov 2018-04-15 15:46 ` AdaMagica 2018-04-15 15:53 ` Dmitry A. Kazakov 2018-04-15 17:17 ` AdaMagica 2018-04-15 17:40 ` Dmitry A. Kazakov 2018-04-15 19:32 ` Egil H H 2018-04-15 20:09 ` Dmitry A. Kazakov 2018-04-25 23:49 ` Randy Brukardt 2018-04-16 5:19 ` J-P. Rosen 2018-04-16 7:30 ` Dmitry A. Kazakov 2018-04-16 7:55 ` J-P. Rosen 2018-04-16 8:13 ` Dmitry A. Kazakov 2018-04-16 8:32 ` J-P. Rosen 2018-04-16 15:26 ` Dmitry A. Kazakov 2018-04-17 9:51 ` AdaMagica 2018-04-17 12:31 ` Dmitry A. Kazakov 2018-04-17 15:37 ` Jeffrey R. Carter 2018-04-17 15:57 ` Dmitry A. Kazakov 2018-04-17 20:16 ` Jeffrey R. Carter 2018-04-17 20:59 ` Dmitry A. Kazakov 2018-04-18 5:20 ` J-P. Rosen 2018-04-17 20:55 ` J-P. Rosen 2018-04-17 21:23 ` Dmitry A. Kazakov 2018-04-18 5:26 ` J-P. Rosen 2018-04-26 0:02 ` Randy Brukardt 2018-04-18 8:06 ` AdaMagica 2018-04-18 8:25 ` Dmitry A. Kazakov 2018-04-18 8:52 ` Egil H H 2018-04-18 9:58 ` Dmitry A. Kazakov 2018-04-18 11:33 ` J-P. Rosen 2018-04-18 11:58 ` Dmitry A. Kazakov 2018-04-18 12:00 ` J-P. Rosen 2018-04-18 12:25 ` Dmitry A. Kazakov 2018-04-18 13:51 ` J-P. Rosen 2018-04-18 14:12 ` Dmitry A. Kazakov 2018-04-18 14:52 ` J-P. Rosen 2018-04-18 15:04 ` Dmitry A. Kazakov 2018-04-18 20:26 ` AdaMagica 2018-04-18 21:00 ` Dmitry A. Kazakov 2018-04-18 20:40 ` AdaMagica 2018-04-19 7:34 ` Simon Wright 2018-04-18 21:29 ` J-P. Rosen 2018-04-19 7:32 ` Dmitry A. Kazakov 2018-04-26 0:04 ` Randy Brukardt 2018-04-26 8:56 ` Dmitry A. Kazakov 2018-04-26 22:10 ` Randy Brukardt 2018-04-27 4:48 ` J-P. Rosen 2018-04-27 20:52 ` Randy Brukardt 2018-04-17 11:16 ` J-P. Rosen 2018-04-17 12:47 ` Dmitry A. Kazakov 2018-04-17 14:08 ` J-P. Rosen 2018-04-17 14:47 ` Dmitry A. Kazakov 2018-04-17 22:00 ` Robert A Duff 2018-04-18 7:25 ` Dmitry A. Kazakov 2018-04-25 23:54 ` Randy Brukardt 2018-04-26 16:22 ` Jeffrey R. Carter 2018-04-26 16:43 ` Dmitry A. Kazakov 2018-04-26 20:19 ` J-P. Rosen 2018-04-16 9:19 ` AdaMagica 2018-04-16 15:15 ` Dmitry A. Kazakov 2018-04-19 20:39 ` G. B. 2018-04-20 7:27 ` Dmitry A. Kazakov 2018-04-25 23:46 ` Randy Brukardt 2018-04-26 9:03 ` Dmitry A. Kazakov 2018-04-26 22:25 ` Randy Brukardt 2018-04-27 7:37 ` Dmitry A. Kazakov 2018-04-27 8:32 ` AdaMagica 2018-04-27 8:57 ` Dmitry A. Kazakov 2018-04-27 21:08 ` Randy Brukardt 2018-04-28 8:35 ` Dmitry A. Kazakov 2018-04-29 17:41 ` AdaMagica 2018-04-29 19:36 ` Dmitry A. Kazakov 2018-04-30 12:27 ` AdaMagica 2018-04-30 13:03 ` Dmitry A. Kazakov 2018-04-30 16:52 ` Jeffrey R. Carter 2018-04-30 17:06 ` Dmitry A. Kazakov 2018-05-01 9:17 ` AdaMagica 2018-05-01 9:40 ` Dmitry A. Kazakov 2018-05-01 11:18 ` Jeffrey R. Carter 2018-05-01 11:27 ` Dmitry A. Kazakov 2018-05-01 15:54 ` Niklas Holsti 2018-05-02 14:34 ` AdaMagica 2018-05-02 14:50 ` Dmitry A. Kazakov 2018-05-01 2:27 ` Randy Brukardt 2018-05-01 6:59 ` Dmitry A. Kazakov
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox