* Re: idiom for task termination? [not found] <32FA10EF.32A@bix.com> @ 1997-02-07 0:00 ` Robert A Duff 1997-02-07 0:00 ` Tom Moran 1997-02-07 0:00 ` Mats Weber 1997-02-08 0:00 ` Matthew Heaney 1 sibling, 2 replies; 10+ messages in thread From: Robert A Duff @ 1997-02-07 0:00 UTC (permalink / raw) In article <32FA10EF.32A@bix.com>, Tom Moran <tmoran@bix.com> wrote: >What's a good idiom for terminating tasks inside library packages? >If I build a re-usable package which contains an internal task which >has an 'entry quit' but does not have a select-terminate alternative, Why not add a terminate alternative? That's what it's for... There are cases where terminate alts don't work. E.g., if the task in question is communicating with others via entry calls (perhaps to protected objects), then you can't use a terminate alt. But in your case, the task must wait on Quit periodically, using an accept statement. So why not get rid of Quit, and use a terminate alt in this case? >I want to guarantee that it does in fact terminate even if the user's >main program fails to call 'quit' (eg, dies on an unhandled exception). > I can declare type heartbeat_type is new >ada.finalization.controlled..., >make a finalize routine for it that calls my 'quit', and then tell the Or simply abort the task. Calling Quit may well be cleaner, though. >user of my package that he should declare an object of this type in >his main program. I think that will work, but it requires rather >more correct action on the part of the user of my re-usable package >than I'd like to depend on. If he puts his declaration in the wrong >place, makes several such declarations, or skips it entirely, bad, and >non-obvious, things could happen. > Any better techniques? Well, if you have many such tasks, you could write a library package that handles all of them. Each package that declares a task would register its termination action with this lib package, and the main subprogram would call something that says "do all the termination actions". Then, the main subprogram just has to remember to call this one procedure, rather than one for each such "reusable" library package. I admit this doesn't completely solve the problem. Note that your controlled object can't be declared in the library package itself, since finalization happens *after* awaiting tasks. As you say, it needs to be one level more dynamically nested (i.e. in the main subprogram). Another idea, which may or may not work in your case, would be to replace the task in question with a protected object. Protected objects go away "automatically", thus avoiding the issue. - Bob ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: idiom for task termination? 1997-02-07 0:00 ` idiom for task termination? Robert A Duff @ 1997-02-07 0:00 ` Tom Moran 1997-02-07 0:00 ` Mats Weber 1 sibling, 0 replies; 10+ messages in thread From: Tom Moran @ 1997-02-07 0:00 UTC (permalink / raw) > the task must wait on Quit periodically, using an accept > statement. So why not get rid of Quit, and use a terminate alt in this > case? Actually it does not wait on Quit, but does a Select, with an 'accept Quit' alternative and an 'else' alternative - so it can't have an terminate alternative. ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: idiom for task termination? 1997-02-07 0:00 ` idiom for task termination? Robert A Duff 1997-02-07 0:00 ` Tom Moran @ 1997-02-07 0:00 ` Mats Weber 1997-02-18 0:00 ` Robert A Duff 1 sibling, 1 reply; 10+ messages in thread From: Mats Weber @ 1997-02-07 0:00 UTC (permalink / raw) Robert A Duff wrote: > > In article <32FA10EF.32A@bix.com>, Tom Moran <tmoran@bix.com> wrote: > >What's a good idiom for terminating tasks inside library packages? > >If I build a re-usable package which contains an internal task which > >has an 'entry quit' but does not have a select-terminate alternative, > > Why not add a terminate alternative? That's what it's for... Because tasks whose masters are library units other than the main program are not required to terminate, and the terminate alternative needs not be chosen. Most implementations still terminate them (their master is the hidden task that calls the main program) but you can't count on this to happen in a portable manner. BTW has Ada 95 changed anything on this ? ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: idiom for task termination? 1997-02-07 0:00 ` Mats Weber @ 1997-02-18 0:00 ` Robert A Duff 0 siblings, 0 replies; 10+ messages in thread From: Robert A Duff @ 1997-02-18 0:00 UTC (permalink / raw) In article <32FB6A6A.431E@elca-matrix.ch>, Mats Weber <Mats.Weber@elca-matrix.ch> wrote: >Robert A Duff wrote: >> >> In article <32FA10EF.32A@bix.com>, Tom Moran <tmoran@bix.com> wrote: >> >What's a good idiom for terminating tasks inside library packages? >> >If I build a re-usable package which contains an internal task which >> >has an 'entry quit' but does not have a select-terminate alternative, >> >> Why not add a terminate alternative? That's what it's for... > >Because tasks whose masters are library units other than the main >program are not required to terminate, and the terminate alternative >needs not be chosen. This was not true in Ada 83, and is not true in Ada 95. The RM83 was not clear on this point, but AI-399 "clarifies" it. And (I hope) RM95 is clear on this point. In Ada 95, a task object declared immediately within a library package depends directly on the environment task (not the package), and the normal rules apply to terminate alternatives in this case (that is, if all the tasks are waiting at terminate alts, then the env task and all its dependents terminate). - Bob ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: idiom for task termination? [not found] <32FA10EF.32A@bix.com> 1997-02-07 0:00 ` idiom for task termination? Robert A Duff @ 1997-02-08 0:00 ` Matthew Heaney 1997-02-09 0:00 ` Tom Moran 1997-02-10 0:00 ` Mats Weber 1 sibling, 2 replies; 10+ messages in thread From: Matthew Heaney @ 1997-02-08 0:00 UTC (permalink / raw) In article <32FA10EF.32A@bix.com>, tmoran@bix.com wrote: >What's a good idiom for terminating tasks inside library packages? >If I build a re-usable package which contains an internal task which >has an 'entry quit' but does not have a select-terminate alternative, >I want to guarantee that it does in fact terminate even if the user's >main program fails to call 'quit' (eg, dies on an unhandled exception). There's no such thing as "main program fails to call quit." Stop playing these "what if" games: you either build a correct, working system, or you don't. Bertrand Meyer popularized the concept of "programming by contract." An abstraction provides a service by stating what it guarantees will happen, provided that the client guarantees he'll do what the abstraction requires. An abstraction states that there is a certain protocol that must be followed for everything to work as advertised. In particular, this supplier doesn't have anything to say about what will happen if the client fails to obey that protocol. This is the only way to build large systems: everyone does their job, without worrying about whether other components break the rules. Just build the system right, so no rules are broken. A simple example is that often library-level packages contain an Initialize method. The abstraction requires that the Initiailze method be called in order for the other operations to work. It does not worry about whether Initialize gets called; it has to be called. It not, then there's an error in some other part of the sytem, so fix that. So don't bother trying to guarantee that you can still quit if your client doesn't tell you to quit. Are you required to be told to quit, or not? A common idiom with tasks is to have Start_Up and Shut_Down alternatives. This gives the application the ability to do some initialization and finalization, such as opening and closing a device. It looks like this package P is procedure Initialize (...); procedure Finalize; ... end; package body P is task T is entry Start_Up (...); entry Shut_Down; entry E1; ... end; procedure Initialize (...) is begin T.Start_Up (...); end; procedure Finalize is begin T.Shut_Down; end; task T is begin select accept Start_Up (...) do ... end Start_Up; or terminate; end select; Main: loop select accept Shut_Down do ... end; exit Main; or accept E1; ... end select; end loop Main; end T; end P; The protocol is as follows: If you don't call Initialize, then you must not call Finalize. And I guarantee that I'll terminate. If you do call Initialize, then you must call Finalize too. And I'll guarantee that I'll terminate. Task T doesn't worry about Shut_Down being called, without Start_Up already having been called. Nor does it worry about Start_Up being called again, once it's already been called. Nor does it worry about Shut_Down not being called, once Start_Up has been called. If you need to be told to quit, then that's what you require to terminate. Period. If the client fails to call quit, then it has the error, so spend your time fixing that, instead of worrying about all these "what happens if..." scenarios. -------------------------------------------------------------------- Matthew Heaney Software Development Consultant <mailto:matthew_heaney@acm.org> (818) 985-1271 ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: idiom for task termination? 1997-02-08 0:00 ` Matthew Heaney @ 1997-02-09 0:00 ` Tom Moran 1997-02-10 0:00 ` Matthew Heaney 1997-02-10 0:00 ` Mats Weber 1 sibling, 1 reply; 10+ messages in thread From: Tom Moran @ 1997-02-09 0:00 UTC (permalink / raw) Wow, what a great fire and brimstone, show no mercy, cast the sinners into the outer darkness, Sunday sermon! I look forward to a great wave of "repent and reform". In the meantime, however, I'm one of those craven sorts who'd rather have users than moral superiority. If I tell users of my package "if, during debugging, you get an unhandled exception, use of my package will cause the program to hang forever, and if you have the OS terminate it you won't get any exception name or traceback" I would expect to have few takers. I could tell the user "if you use my package you must be sure to include a 'when others => toms.quit;' exception handler. The original question, though, was how can I use a task internal to a library package without special demands on the user. In my experience, saying "but I told you to do such and such and you failed to do it" is not a successful approach to having satisfied users. There's also the problem of some users having compilers which are unable to give exception tracebacks. It's been suggested that a mere log2(N) runs with various breakpoint settings will give them a traceback, but this package runs in an environment where the sequence and timing of external input would have to be duplicated on each of those runs, which is inconvenient if not impossible. ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: idiom for task termination? 1997-02-09 0:00 ` Tom Moran @ 1997-02-10 0:00 ` Matthew Heaney 0 siblings, 0 replies; 10+ messages in thread From: Matthew Heaney @ 1997-02-10 0:00 UTC (permalink / raw) In article <32FE308B.251D@bix.com>, tmoran@bix.com wrote: >Wow, what a great fire and brimstone, show no mercy, cast the sinners >into the outer darkness, Sunday sermon! I look forward to a great wave >of "repent and reform". For the real sermon, read Object-Oriented Software Construction Chapter 7, Systematic approaches to software construction Bertrand Meyer Prentice Hall <the 2nd ed is in the pipe> System Development Chapter 12, The Input Subsystem and Errors Micheal Jackson Prentice Hall If I had to identify the 1 or 2 references that changed my life as a programmer, then these 2 would be it. Read them and you won't regret it! Amen. matt -------------------------------------------------------------------- Matthew Heaney Software Development Consultant <mailto:matthew_heaney@acm.org> (818) 985-1271 ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: idiom for task termination? 1997-02-08 0:00 ` Matthew Heaney 1997-02-09 0:00 ` Tom Moran @ 1997-02-10 0:00 ` Mats Weber 1997-02-10 0:00 ` Matthew Heaney 1 sibling, 1 reply; 10+ messages in thread From: Mats Weber @ 1997-02-10 0:00 UTC (permalink / raw) > package P is > procedure Initialize (...); > procedure Finalize; > ... > end; If you modify this abstract state machine to make it an abstract state type, then you can somewhat alleviate the termination problems: package P is type ADT is limited private; procedure Init (X : in out ADT; ...); procedure Finalize (X : in out ADT); ... private task type ADT is entry Init (...); entry Stop; entry E1; end ADT; end; The user of P will then delcare an object of type P.ADT, which will make him the master of the task object, and the terminate alternative in the body of ADT will be selected when the program terminates. ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: idiom for task termination? 1997-02-10 0:00 ` Mats Weber @ 1997-02-10 0:00 ` Matthew Heaney 1997-02-11 0:00 ` Tom Moran 0 siblings, 1 reply; 10+ messages in thread From: Matthew Heaney @ 1997-02-10 0:00 UTC (permalink / raw) In article <32FF32D7.67D2@elca-matrix.ch>, Mats.Weber@elca-matrix.ch wrote: >The user of P will then delcare an object of type P.ADT, which will make >him the master of the task object, and the terminate alternative in the >body of ADT will be selected when the program terminates. But the question is, Does the select even have a terminate alternative? If you need to do some work before you terminate - such as shut down a device or close a file - then you have to be told explicity to shut down. You are correct that a terminate alternative would do the trick, but only if the server task doesn't have to do anything before terminating. That's why I asked if the abstraction required to be told to quit. Asking, How do I quit if my client forgets to tell me to quit?, is a little like asking, What happens if I use Unchecked_Conversion to return a value outside the range of the target type? Of course, the behaviour is undefined, so don't do it. matt -------------------------------------------------------------------- Matthew Heaney Software Development Consultant <mailto:matthew_heaney@acm.org> (818) 985-1271 ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: idiom for task termination? 1997-02-10 0:00 ` Matthew Heaney @ 1997-02-11 0:00 ` Tom Moran 0 siblings, 0 replies; 10+ messages in thread From: Tom Moran @ 1997-02-11 0:00 UTC (permalink / raw) > But the question is, Does the select even have a terminate alternative? If > you need to do some work before you terminate - such as shut down a device > or close a file - then you have to be told explicity to shut down. I think if that was the problem then the 'last wishes' example in Burns & Wellings - declare a controlled type inside the task body and have its Finalize do the last wishes of the departing task - would work. But here I'm trying to execute a terminate alternative when the rules of Ada won't let me put in a terminate alternative. And more to the point, I want to gracefully catch a possible user error - failing to tell me to quit - with as little burden on the user as possible. (If the user didn't make mistakes, even during debugging, then he would have called my Quit routine.) If the user just does a 'with' of my package, and then the first statement of his program causes an unhandled exception, I really don't want to simply hang and force him to use the OS to abort the task and lose any exception information that might be present and useful. Various techniques come fairly close, but so far I've seen none that actually provide this. ^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~1997-02-18 0:00 UTC | newest] Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- [not found] <32FA10EF.32A@bix.com> 1997-02-07 0:00 ` idiom for task termination? Robert A Duff 1997-02-07 0:00 ` Tom Moran 1997-02-07 0:00 ` Mats Weber 1997-02-18 0:00 ` Robert A Duff 1997-02-08 0:00 ` Matthew Heaney 1997-02-09 0:00 ` Tom Moran 1997-02-10 0:00 ` Matthew Heaney 1997-02-10 0:00 ` Mats Weber 1997-02-10 0:00 ` Matthew Heaney 1997-02-11 0:00 ` Tom Moran
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox