comp.lang.ada
 help / color / mirror / Atom feed
* 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?
       [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-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-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-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

* 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

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