* Finalization of a record containing a task @ 2005-02-16 20:35 Bj?rn 2005-02-16 20:49 ` Stephen Leake 0 siblings, 1 reply; 15+ messages in thread From: Bj?rn @ 2005-02-16 20:35 UTC (permalink / raw) I'm trying to implement a form of self modifying ADT, containing an active task. I would prefer that the user of the ADT not need to do any "extra" operations on the ADT when the user is finished with it, rather have the task terminate automatically when the type goes out of scope. I do not see how I can manage this since the ADT does not seem to finalize as long as the tasks have not terminated. How can I solve this? Should I rather try a different approach? Currently it looks something like this: package PKG is type T_ADT is new Limited_Controlled with private ... private task type T_Worker is entry Start; entry Stop; ... end task; procedure Initialize (T : in out T_ADT); procedure Finalize (T : in out T_ADT); type T_ADT is new Limited_Controlled with record X : Some_Type; Worker : T_Worker; end record; end PKG; package body PKG is task T_Worker is {Inner task of T_Worker} begin loop select accept Start; or accept Stop; or ... or delay until Some_Time; end select; end loop; end PKG; Best regards, Bj�rn ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: Finalization of a record containing a task 2005-02-16 20:35 Finalization of a record containing a task Bj?rn @ 2005-02-16 20:49 ` Stephen Leake 2005-02-16 21:20 ` Adrien Plisson ` (2 more replies) 0 siblings, 3 replies; 15+ messages in thread From: Stephen Leake @ 2005-02-16 20:49 UTC (permalink / raw) To: comp.lang.ada ssh9614@hotmail.com (Bj?rn) writes: > I'm trying to implement a form of self modifying ADT, containing an > active task. > > I would prefer that the user of the ADT not need to do any "extra" > operations on the ADT when the user is finished with it, rather have > the task terminate automatically when the type goes out of scope. > > I do not see how I can manage this since the ADT does not seem to > finalize as long as the tasks have not terminated. you need to have a 'select' statement, with an open 'terminate' alternative. > package body PKG is > task T_Worker is > {Inner task of T_Worker} > begin > loop > select > accept Start; > or > accept Stop; > or > ... > or > delay until Some_Time; or terminate; > end select; > end loop; > end PKG; -- -- Stephe ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: Finalization of a record containing a task 2005-02-16 20:49 ` Stephen Leake @ 2005-02-16 21:20 ` Adrien Plisson 2005-02-16 22:09 ` Robert A Duff 2005-02-17 9:13 ` Dmitry A. Kazakov 2005-02-16 22:08 ` Robert A Duff 2005-02-17 17:50 ` Bj?rn 2 siblings, 2 replies; 15+ messages in thread From: Adrien Plisson @ 2005-02-16 21:20 UTC (permalink / raw) Stephen Leake wrote: > ssh9614@hotmail.com (Bj?rn) writes: >>I do not see how I can manage this since the ADT does not seem to >>finalize as long as the tasks have not terminated. > > you need to have a 'select' statement, with an open 'terminate' > alternative. alternately, since T_ADT is Limited_Controlled, you may abort the inner task in its Finalize (!! baaad !!) -- rien ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: Finalization of a record containing a task 2005-02-16 21:20 ` Adrien Plisson @ 2005-02-16 22:09 ` Robert A Duff 2005-02-17 8:24 ` Adrien Plisson 2005-02-17 9:13 ` Dmitry A. Kazakov 1 sibling, 1 reply; 15+ messages in thread From: Robert A Duff @ 2005-02-16 22:09 UTC (permalink / raw) Adrien Plisson <aplisson-news@stochastique.net> writes: > Stephen Leake wrote: > > > ssh9614@hotmail.com (Bj?rn) writes: > >>I do not see how I can manage this since the ADT does not seem to > >>finalize as long as the tasks have not terminated. > > you need to have a 'select' statement, with an open 'terminate' > > alternative. > > alternately, since T_ADT is Limited_Controlled, you may abort the inner > task in its Finalize (!! baaad !!) But the problem is that the program hangs, waiting for termination of the task, *before* it calls the Finalize that does the abort (or calls the Stop entry, in the original example). - Bob ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: Finalization of a record containing a task 2005-02-16 22:09 ` Robert A Duff @ 2005-02-17 8:24 ` Adrien Plisson 2005-02-18 0:17 ` Robert A Duff 0 siblings, 1 reply; 15+ messages in thread From: Adrien Plisson @ 2005-02-17 8:24 UTC (permalink / raw) Robert A Duff wrote: > Adrien Plisson <aplisson-news@stochastique.net> writes: >>alternately, since T_ADT is Limited_Controlled, you may abort the inner >>task in its Finalize (!! baaad !!) > > > But the problem is that the program hangs, waiting for termination of > the task, *before* it calls the Finalize that does the abort > (or calls the Stop entry, in the original example). euh... yes, you are right. i do remember now that when i did that, i was using an access to the task type. anyway, it is a very bad idea since aborting the task may have a side effect: you don't know what was going on at the time you abort the task, so the state of the data accessed by the task is undefined. -- rien ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: Finalization of a record containing a task 2005-02-17 8:24 ` Adrien Plisson @ 2005-02-18 0:17 ` Robert A Duff 0 siblings, 0 replies; 15+ messages in thread From: Robert A Duff @ 2005-02-18 0:17 UTC (permalink / raw) Adrien Plisson <aplisson-news@stochastique.net> writes: > anyway, it is a very bad idea since aborting the task may have a side > effect: you don't know what was going on at the time you abort the task, > so the state of the data accessed by the task is undefined. Yes! If you use abort (including select-then-abort) then any data modified by the abortable code can be destroyed in an unpredictable fashion. So you have to avoid looking at that data after the abort, or make sure the data is updated in abort-deferred regions, or.... It is *very* difficult to get this right in a large system. - Bob ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: Finalization of a record containing a task 2005-02-16 21:20 ` Adrien Plisson 2005-02-16 22:09 ` Robert A Duff @ 2005-02-17 9:13 ` Dmitry A. Kazakov 2005-02-18 0:13 ` Robert A Duff 1 sibling, 1 reply; 15+ messages in thread From: Dmitry A. Kazakov @ 2005-02-17 9:13 UTC (permalink / raw) On Wed, 16 Feb 2005 22:20:27 +0100, Adrien Plisson wrote: > Stephen Leake wrote: > >> ssh9614@hotmail.com (Bj?rn) writes: >>>I do not see how I can manage this since the ADT does not seem to >>>finalize as long as the tasks have not terminated. >> >> you need to have a 'select' statement, with an open 'terminate' >> alternative. > > alternately, since T_ADT is Limited_Controlled, you may abort the inner > task in its Finalize (!! baaad !!) No, there is no way to gracefully complete task components of upon finalization of the controlled object. The finalization model does not allow this, see Robert Duff's post. (Hypothetically, if there were class-wide destructors, one would be able to do that.) So in most cases one is forced to use access-to-task components rather than plain task ones. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: Finalization of a record containing a task 2005-02-17 9:13 ` Dmitry A. Kazakov @ 2005-02-18 0:13 ` Robert A Duff 2005-02-18 2:34 ` Randy Brukardt 2005-02-18 11:27 ` Dmitry A. Kazakov 0 siblings, 2 replies; 15+ messages in thread From: Robert A Duff @ 2005-02-18 0:13 UTC (permalink / raw) "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes: >... (Hypothetically, if there were > class-wide destructors, one would be able to do that.) Sounds interesting. Can you give details of what you mean? >... So in most cases one > is forced to use access-to-task components rather than plain task ones. Yes, but if you declare the object in a library package, you'll still have the same problem with finalization happening too late. - Bob ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: Finalization of a record containing a task 2005-02-18 0:13 ` Robert A Duff @ 2005-02-18 2:34 ` Randy Brukardt 2005-02-18 11:27 ` Dmitry A. Kazakov 1 sibling, 0 replies; 15+ messages in thread From: Randy Brukardt @ 2005-02-18 2:34 UTC (permalink / raw) "Robert A Duff" <bobduff@shell01.TheWorld.com> wrote in message news:wccll9mu3m7.fsf@shell01.TheWorld.com... ... > >... So in most cases one > > is forced to use access-to-task components rather than plain task ones. > > Yes, but if you declare the object in a library package, you'll > still have the same problem with finalization happening too late. Claw uses Ada.Task_Identification.Is_Callable to handle this problem. (Unfortunately, some compilers get this wrong.) That only works if you trying to handle this at the library level (having some other solution for nested objects). In our case, the task is a library-level one that all of the objects share; the problem is that the task can only close when all of the objects are gone (as they potentially could use it for executing commands), but of course the task has to go away before any library-level objects are finalized. The solution was to use Ada.Task_Identification.Is_Callable to see if the main subprogram has completed. If it has, the task exits, allowing finalization to continue. (Otherwise, a Claw program would hang if objects are not destroyed by the program, which was common when exceptions were raised.) This isn't quite a bullet-proof solution; if the main program does nothing and exits quickly, with all of the real work done by library tasks, this will cause premature shutdown of the application. (Claw has a way to turn off this termination for this reason, but the default behavior is less surprising in the *vast* majority of programs.) This eliminated the confusing hangs, and made Claw a lot more usable. (We've also got a bunch of code to detect whether the implementation actually provides a meaningful result from this function, but hopefully this now works on implementations.) The trick is to get a task id for the environment task. That can be done by asking for current task during library-level elaboration by declaring a constant directly in a library package spec or body: Env_Task_Id : constant Ada.Task_Identification.Task_ID := Ada.Task_Identification.Current_Task; and then using it as needed. Randy. ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: Finalization of a record containing a task 2005-02-18 0:13 ` Robert A Duff 2005-02-18 2:34 ` Randy Brukardt @ 2005-02-18 11:27 ` Dmitry A. Kazakov 1 sibling, 0 replies; 15+ messages in thread From: Dmitry A. Kazakov @ 2005-02-18 11:27 UTC (permalink / raw) On 17 Feb 2005 19:13:36 -0500, Robert A Duff wrote: > "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes: > >>... (Hypothetically, if there were >> class-wide destructors, one would be able to do that.) > > Sounds interesting. Can you give details of what you mean? The idea is to have user-defined initialization / finalization of class-wide objects. After all, T'Class is as type as T, why shouldn't it have ctors? Because presently tagged objects are view-convertible to their classes, that automatically implies, that even specific tagged objects have to be initialized / finalized as classes. So let us have: type A is new Ada.Finalization....; type B is new A with ...; Then, to initialize B, we have to: 1. initialize B (and A from there) 2. initialize B'Class -- presently empty 3. initialize A'Class -- presently empty To finalize B: 1. finalize A'Class -- presently empty 2. finalize B'Class -- presently empty 3. finalize B (and A from there) Because now we have something class-wide to dispatch from that could solve the problem of dispatching from constructors. One will just dispatch from: Class_Initialize (Object : in out A'Class); At this stage B (or whatsoever derived object) is fully constructed, so we can safely dispatch on Object. Same with task components (and hypothetically with task ancestors): Class_Finalize could call Die_At_Once entry of its task component. >>... So in most cases one >> is forced to use access-to-task components rather than plain task ones. > > Yes, but if you declare the object in a library package, you'll > still have the same problem with finalization happening too late. Yes. ---------------------------- Should Ada some day have classes for non-tagged objects, then class-wide constructors / destructors would be called each time T is converted to T'Class and back. That would be a real conversion then, which at least adds / removes the type tag. It could become very interesting for by-reference parameter passing, though. For example: type A is ...; procedure Foo (Object : A); -- A is by-reference here type B is new A ...; X : constant A'Class := Some_B; begin Foo (X); upon dispatch to A.Foo, X has to be converted to plain A. For this it is first demoted from class by finalizing A'Class and then B'Class. Now Foo is ready to call. After Foo's completion, and even if an exception is propagated, X need to be heighten back to B'Class and A'Class. No matter, if it is a constant! (:-)) -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: Finalization of a record containing a task 2005-02-16 20:49 ` Stephen Leake 2005-02-16 21:20 ` Adrien Plisson @ 2005-02-16 22:08 ` Robert A Duff 2005-02-21 13:20 ` Craig Carey 2005-02-17 17:50 ` Bj?rn 2 siblings, 1 reply; 15+ messages in thread From: Robert A Duff @ 2005-02-16 22:08 UTC (permalink / raw) Stephen Leake <stephen_leake@acm.org> writes: > you need to have a 'select' statement, with an open 'terminate' > alternative. That works in some cases, but you can't mix delay alternatives with terminate alternatives. Maybe you could replace the delay with an accept, and arrange for some other task to call that entry periodically. But then how do you get rid of that *other* task? You also can't mix entry calls with terminate alternatives, so if the task wants to talk to a protected object, you're stuck. > > package body PKG is > > task T_Worker is > > {Inner task of T_Worker} > > begin > > loop > > select > > accept Start; > > or > > accept Stop; > > or > > ... > > or > > delay until Some_Time; > > or terminate; > > > end select; > > end loop; > > end PKG; > > -- > -- Stephe - Bob ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: Finalization of a record containing a task 2005-02-16 22:08 ` Robert A Duff @ 2005-02-21 13:20 ` Craig Carey 2005-02-21 21:41 ` Robert A Duff 0 siblings, 1 reply; 15+ messages in thread From: Craig Carey @ 2005-02-21 13:20 UTC (permalink / raw) On 16 Feb 2005 17:08:30 -0500, Robert A Duff wrote: > [...] but you can't mix delay alternatives with >terminate alternatives. ... >You also can't mix entry calls with terminate alternatives, so if the >task wants to talk to a protected object, you're stuck. ... Are all those restrictions on select statements actually important to the language implementors ?. The current design of select statement seems to be identical to the c. 1982 design. Perhaps a redesign could occur. -- C Carey ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: Finalization of a record containing a task 2005-02-21 13:20 ` Craig Carey @ 2005-02-21 21:41 ` Robert A Duff 2005-02-22 0:15 ` Randy Brukardt 0 siblings, 1 reply; 15+ messages in thread From: Robert A Duff @ 2005-02-21 21:41 UTC (permalink / raw) Craig Carey <research@ijs.co.nz> writes: > On 16 Feb 2005 17:08:30 -0500, Robert A Duff wrote: > > [...] but you can't mix delay alternatives with > >terminate alternatives. > ... > >You also can't mix entry calls with terminate alternatives, so if the > >task wants to talk to a protected object, you're stuck. > ... > > Are all those restrictions on select statements actually important to the > language implementors ?. > > The current design of select statement seems to be identical to the > c. 1982 design. Perhaps a redesign could occur. From a practical point of view: it's unlikely that any such redesign will happen any time soon. The feature set for Ada 2005 is pretty much closed. Who knows what the situation will be in 2015? But it's an interesting question, which I've thought a lot about in the past. It's not such much an ease of implementation issue. The question is whether the semantics can make sense. At a high level, "terminate" means, roughly, "if there's no possibility that I can wake up again, then terminate me." The Ada 83 rules are constructed so that if all tasks dependent upon a given master are either terminated or waiting on an open terminate alternative, then none of them can possibly wake up, so it's safe to terminate them all. (One exception: an interrupt could wake them up, which Ada 83 handles by saying "implementation defined" -- something of a copout.) This is based on the fact that tasks can only accept their own entries, and the fact that you can't call a task's entries without being inside its master. (Interrupts can come in from out of the blue.) But if we allowed: select X.Some_Entry(...); or terminate; end select; then X could outlive this task. So how do we know when it's safe to terminate this task? I'd be interested in hearing any ideas -- it seems like it could be a useful capability, if the rules could make sense! X could be a task or a protected object. Requeue makes it even more "interesting". ;-) Imagine the call being requeued here, there, and elsewhere, unbeknownst to the caller. I think a delay statement is similar to an entry call -- you can think of it as a call on a protected object's entry, such that the barrier will become true at some time. So if the problem can be solved for entry calls, it can be solved for delay alternatives. ---- Note that it was proposed during Ada 9X to allow multiple entry calls, as in: select X.Some_Entry(...); or Y.Some_Other_Entry(...); -- illegal! end select; which would mean pick whichever entry call becomes ready first (similar to the multiple accept case). Sadly, that didn't make it into Ada 95 (nor Ada 2005). I don't know of any semantic anomalies; I think it was just considered too hard to implement. - Bob ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: Finalization of a record containing a task 2005-02-21 21:41 ` Robert A Duff @ 2005-02-22 0:15 ` Randy Brukardt 0 siblings, 0 replies; 15+ messages in thread From: Randy Brukardt @ 2005-02-22 0:15 UTC (permalink / raw) "Robert A Duff" <bobduff@shell01.TheWorld.com> wrote in message news:wccll9h4mm6.fsf@shell01.TheWorld.com... ... > Note that it was proposed during Ada 9X to allow multiple entry calls, > as in: > > select > X.Some_Entry(...); > or > Y.Some_Other_Entry(...); -- illegal! > end select; > > which would mean pick whichever entry call becomes ready first > (similar to the multiple accept case). > Sadly, that didn't make it into Ada 95 (nor Ada 2005). > I don't know of any semantic anomalies; I think it was just > considered too hard to implement. Nothing sad about it. The Ada 9X office required all of the U-I teams to make a detailed report. I remember spending a lot of time on that. The conclusion of all of the reports was that it would have ended being implemented as a busy-wait loop on virtually all systems, and thus it would look cheap while the implementation would have been very expensive. (And the users that were clamoring for it, the hard real-time people, would have never actually used it in practice.) Those reports are still available somewhere in the archives (archive.adaic.com). Specifically, the calls above would end up implemented similarly to: loop select X.Some_Entry(...); else null; end select; select Y.Some_Other_Entry(...); -- illegal! else null; end select; delay <some appropriate amount>; -- Let other tasks run. end loop; so you might as well write the above if it really is needed. Randy. ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: Finalization of a record containing a task 2005-02-16 20:49 ` Stephen Leake 2005-02-16 21:20 ` Adrien Plisson 2005-02-16 22:08 ` Robert A Duff @ 2005-02-17 17:50 ` Bj?rn 2 siblings, 0 replies; 15+ messages in thread From: Bj?rn @ 2005-02-17 17:50 UTC (permalink / raw) Ok. I will try doing this in some other way then. Thank you all for clarification and suggestions! Best regards, Bj�rn ^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2005-02-22 0:15 UTC | newest] Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2005-02-16 20:35 Finalization of a record containing a task Bj?rn 2005-02-16 20:49 ` Stephen Leake 2005-02-16 21:20 ` Adrien Plisson 2005-02-16 22:09 ` Robert A Duff 2005-02-17 8:24 ` Adrien Plisson 2005-02-18 0:17 ` Robert A Duff 2005-02-17 9:13 ` Dmitry A. Kazakov 2005-02-18 0:13 ` Robert A Duff 2005-02-18 2:34 ` Randy Brukardt 2005-02-18 11:27 ` Dmitry A. Kazakov 2005-02-16 22:08 ` Robert A Duff 2005-02-21 13:20 ` Craig Carey 2005-02-21 21:41 ` Robert A Duff 2005-02-22 0:15 ` Randy Brukardt 2005-02-17 17:50 ` Bj?rn
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox