comp.lang.ada
 help / color / mirror / Atom feed
From: "Robert I. Eachus" <rieachus@comcast.net>
Subject: Re: task time-out&abort
Date: Mon, 18 Jul 2005 12:11:47 -0400
Date: 2005-07-18T12:11:47-04:00	[thread overview]
Message-ID: <5eWdnYcV-YxHSUbfRVn-1g@comcast.com> (raw)
In-Reply-To: <wccwtocsx6i.fsf@shell01.TheWorld.com>

(The point of this post is to give some guidance on which approach to 
use...)

Robert A Duff wrote:
> 
> You can put the Horribly_Complicated_Recursive_Function inside an ATC:
> 
>     select
>         delay 5.0;
>     then abort
>         Horribly_Complicated_Recursive_Function...
>     end select;
> 
> And you can pass the time-out as a parameter to the entry call,
> if you like.

This is the right idiom for handling ill-behaved computations.  But as 
written it is infrequently the best/right solution.

> But be careful!  ATC is a very dangerous feature, which is difficult to
> get right.  And if you get it wrong, you will have nasty
> timing-dependent bugs.

Should I repeat this three times?
> 
> The problem is that any variables modified by
> Horribly_Complicated_Recursive_Function can be destroyed
> when it gets aborted by the timeout.  The usual way to deal with it
> is to do most of the work in local data that nobody else looks at.
> And it can update some more-global thing (like an 'out' parameter of the
> entry) in an abort-deferred way -- using a protected object, or a pragma
> Atomic.

Exactly, and the reason I am commmenting here.  There are really three 
cases:

1) You have no control over and no insight into the Horribly Complicated 
Recursive Function.  In this case, if the timeout happens, your only 
option to (possibly) get a usable result is to start over with a longer 
delay.

2) A much more normal case is that you are doing some sort of iterative 
refinement.  In this case, as Bob points out, you can use a protected 
object to collect each improved result, and when the abort occurs, you 
can use the best result found in the time available.  This is a common 
idiom in flight control software, although the preferred implementation 
computes how long the next iteration will take, and checks to see if 
there is enough time remaining.  (This way you always finish in less 
time than is available, instead of potentially taking a few hundred 
cycles longer.)

3) A nicer implementation in Ada using tasking is possible when each 
iteration takes a limited (and short) time.  This is the implementation 
that has been suggested where the Horribly Complicated Recursive 
Function is wrapped in a task that checks whether the timeout entry has 
been called.

4) The last solution is not to use tasking at all:

declare
   Finish: Ada.Calendar.Time := Ada.Calendar.Clock + Timeout - 

        Iteration_Time_Limit;
begin
   while Ada.Calendar.Clock < Finish loop
     Do_Iteration;
   end loop;
end;
-- use results here.

This of course requires that Horribly Complicated Recursive Function can 
be broken into iterations that are limited in the time required to 
complete.  We are actually back to the beginning at this point, since 
you can use the idioms above to ensure that each iteration completes 
within the time limit.




      reply	other threads:[~2005-07-18 16:11 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2005-06-22 18:08 task time-out&abort e.coli
2005-06-22 18:40 ` Dmitry A. Kazakov
2005-06-23 10:11   ` e.coli
2005-06-23 10:59     ` Dmitry A. Kazakov
2005-06-22 19:44 ` Mark Lorenzen
2005-06-23  1:44 ` Steve
2005-06-23 15:26 ` e.coli
2005-06-23 17:01   ` e.coli
2005-06-24 11:42     ` Marius Amado Alves
2005-06-28 21:31       ` Robert A Duff
2005-06-29  0:32         ` Marius Amado Alves
2005-06-29 20:52   ` Robert A Duff
2005-07-18 16:11     ` Robert I. Eachus [this message]
replies disabled

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox