comp.lang.ada
 help / color / mirror / Atom feed
* task time-out&abort
@ 2005-06-22 18:08 e.coli
  2005-06-22 18:40 ` Dmitry A. Kazakov
                   ` (3 more replies)
  0 siblings, 4 replies; 13+ messages in thread
From: e.coli @ 2005-06-22 18:08 UTC (permalink / raw)


here the code...
------------------------------------
with Ada.Text_Io;
with Ada.Task_Identification;

procedure Semplice2 is --processo genitore

   task Un_Task is--specifica
      entry Uno;
      entry Due;
   end Un_Task;

   task body Un_Task is
   begin
      loop
         select
            accept Uno do
               Ada.Text_Io.Put_Line("foo");
            end Uno;
         or
            accept Due do
               Ada.Text_Io.Put_Line("buffering");
               loop           -- ;)
                  delay(0.0);
               end loop;
               Ada.Text_Io.Put_Line("bar");
            end Due;
         end select;
      end loop;
   end Un_Task;

begin --corpo genitore
   Un_Task.Uno;
   Ada.Text_Io.Put_Line ("wait Horribly long calculation");
   select
      delay 5.0;
      Ada.Text_Io.Put_Line ("Horribly long calculation abandoned");
   then abort
      un_task.due;
   end select;
end Semplice2;
-----------------------------------------

but don't work...
how i can do the five second time out?
thanks




^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: task time-out&abort
  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-22 19:44 ` Mark Lorenzen
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 13+ messages in thread
From: Dmitry A. Kazakov @ 2005-06-22 18:40 UTC (permalink / raw)


On 22 Jun 2005 11:08:23 -0700, e.coli wrote:

> here the code...
> ------------------------------------
> with Ada.Text_Io;
> with Ada.Task_Identification;
> 
> procedure Semplice2 is --processo genitore
> 
>    task Un_Task is--specifica
>       entry Uno;
>       entry Due;
>    end Un_Task;
> 
>    task body Un_Task is
>    begin
>       loop
>          select
>             accept Uno do
>                Ada.Text_Io.Put_Line("foo");
>             end Uno;
>          or
>             accept Due do
>                Ada.Text_Io.Put_Line("buffering");
>                loop           -- ;)
>                   delay(0.0);
>                end loop;
>                Ada.Text_Io.Put_Line("bar");
>             end Due;
>          end select;
>       end loop;
>    end Un_Task;
> 
> begin --corpo genitore
>    Un_Task.Uno;
>    Ada.Text_Io.Put_Line ("wait Horribly long calculation");
>    select
>       delay 5.0;
>       Ada.Text_Io.Put_Line ("Horribly long calculation abandoned");
>    then abort
>       un_task.due;
>    end select;
> end Semplice2;
> -----------------------------------------
> 
> but don't work...
> how i can do the five second time out?
> thanks

It is not clear what you are trying to achieve. The entry point Due engages
the rendezvous and then loops there. Because looping happens during a
rendezvous both participants (Un_Task and the main task) will stay there
forever. Note that a timed entry call puts on a limit for *waiting* for a
rendezvous, it does not limit the rendezvous itself.

---
The rule of thumb: rendezvous (and protected operations) should be as short
as possible.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: task time-out&abort
  2005-06-22 18:08 task time-out&abort e.coli
  2005-06-22 18:40 ` Dmitry A. Kazakov
@ 2005-06-22 19:44 ` Mark Lorenzen
  2005-06-23  1:44 ` Steve
  2005-06-23 15:26 ` e.coli
  3 siblings, 0 replies; 13+ messages in thread
From: Mark Lorenzen @ 2005-06-22 19:44 UTC (permalink / raw)


"e.coli" <maurizio.ferracini@gmail.com> writes:

> here the code...
> ------------------------------------
> with Ada.Text_Io;
> with Ada.Task_Identification;
> 
> procedure Semplice2 is --processo genitore
> 
>    task Un_Task is--specifica
>       entry Uno;
>       entry Due;
>    end Un_Task;
> 
>    task body Un_Task is
>    begin
>       loop
>          select
>             accept Uno do
>                Ada.Text_Io.Put_Line("foo");
>             end Uno;
>          or
>             accept Due do
>                Ada.Text_Io.Put_Line("buffering");
>                loop           -- ;)
>                   delay(0.0);
>                end loop;
>                Ada.Text_Io.Put_Line("bar");
>             end Due;
>          end select;
>       end loop;
>    end Un_Task;
> 
> begin --corpo genitore
>    Un_Task.Uno;
>    Ada.Text_Io.Put_Line ("wait Horribly long calculation");
>    select
>       delay 5.0;
>       Ada.Text_Io.Put_Line ("Horribly long calculation abandoned");
>    then abort
>       un_task.due;
>    end select;
> end Semplice2;
> -----------------------------------------
> 
> but don't work...
> how i can do the five second time out?
> thanks

As I see it, you have a calculation that may take a long time and you
want to abandon that calculation, if some time constraint is
reached. To do it the proper "Ada-way" you will need to use an other
technique, see:

http://www.adaic.com/standards/95aarm/html/AA-9-7-4.html

- Mark Lorenzen



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: task time-out&abort
  2005-06-22 18:08 task time-out&abort e.coli
  2005-06-22 18:40 ` Dmitry A. Kazakov
  2005-06-22 19:44 ` Mark Lorenzen
@ 2005-06-23  1:44 ` Steve
  2005-06-23 15:26 ` e.coli
  3 siblings, 0 replies; 13+ messages in thread
From: Steve @ 2005-06-23  1:44 UTC (permalink / raw)


If you just want to see Asynchronous Transfer of control in action, change 
your example to read:

   task body Un_Task is
   begin
      loop
         select
            accept Uno do
               Ada.Text_Io.Put_Line("foo");
            end Uno;
             loop           -- ;)
                delay(0.0);
             end loop;
         or
            accept Due do
               Ada.Text_Io.Put_Line("buffering");
               Ada.Text_Io.Put_Line("bar");
            end Due;
         end select;
      end loop;
   end Un_Task;

Note: I didn't test this to verify, but I think it will give you the result 
you're looking for.
Uno starts the long operation.  Since the task will not go back to the 
select until the loop is done, your abort should kick in.

Also...
  In my informal view of things, you should minimize the amount of work you 
do inside of an accept block.  During the rendevous, only one of the tasks 
is active, so it kind of defeats the purpose of using a separate task.  In 
fact you could change your example task to:

   task body Un_Task is
   begin
      loop
         select
            accept Uno;
            Ada.Text_Io.Put_Line("foo");
             loop           -- ;)
                delay(0.0);
             end loop;
         or
            accept Due;
            Ada.Text_Io.Put_Line("buffering");
            Ada.Text_Io.Put_Line("bar");
         end select;
      end loop;
   end Un_Task;

Which completely eliminates any work done inside the accept block.

Steve
(The Duck) 





^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: task time-out&abort
  2005-06-22 18:40 ` Dmitry A. Kazakov
@ 2005-06-23 10:11   ` e.coli
  2005-06-23 10:59     ` Dmitry A. Kazakov
  0 siblings, 1 reply; 13+ messages in thread
From: e.coli @ 2005-06-23 10:11 UTC (permalink / raw)


my goal is kill the task if the calculation is long more than 5 sec,.




^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: task time-out&abort
  2005-06-23 10:11   ` e.coli
@ 2005-06-23 10:59     ` Dmitry A. Kazakov
  0 siblings, 0 replies; 13+ messages in thread
From: Dmitry A. Kazakov @ 2005-06-23 10:59 UTC (permalink / raw)


On 23 Jun 2005 03:11:13 -0700, e.coli wrote:

> my goal is kill the task if the calculation is long more than 5 sec,.

I would propose to use a more co-operative way than rather brutal aborting
of a task (which is still possible, of course). What about this:

with Ada.Text_IO;

procedure Semplice2 is --processo genitore
   task Un_Task is
      entry Start;    -- Starts calculation
      entry Drop_It;  -- Aborts calculation
      entry Wait_For; -- Waits for the results
   end Un_Task;

   task body Un_Task is
   begin
      loop
         select
            accept Start;
            Ada.Text_Io.Put_Line ("Start");
            for Iteration in 1..10_000 loop
               select
                  accept Drop_It;
                  goto Cancel;
               else
                  delay 1.0;  -- Doing things
               end select;
            end loop;
            accept Wait_For;
<<Cancel>>  null;            
         or terminate;
         end select;
      end loop;
   end Un_Task;

begin
   Un_Task.Start;
   Ada.Text_Io.Put_Line ("wait for a horribly long calculation");
   select
      delay 5.0;
      un_task.Drop_It;
      Ada.Text_Io.Put_Line ("Horribly long calculation abandoned");
   then abort
      un_task.Wait_For;
      Ada.Text_Io.Put_Line ("Horribly long calculation ready");
   end select;
end Semplice2;

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: task time-out&abort
  2005-06-22 18:08 task time-out&abort e.coli
                   ` (2 preceding siblings ...)
  2005-06-23  1:44 ` Steve
@ 2005-06-23 15:26 ` e.coli
  2005-06-23 17:01   ` e.coli
  2005-06-29 20:52   ` Robert A Duff
  3 siblings, 2 replies; 13+ messages in thread
From: e.coli @ 2005-06-23 15:26 UTC (permalink / raw)


e.coli ha scritto:
> here the code...


i have this simple code...
------------------------------------
  with Ada.Text_Io;

procedure Sempliced2 is

   task A_Task is
      entry Uno;
   end A_Task;

   task body A_Task is
   begin
      loop
         select
         accept Uno do
            Ada.Text_Io.Put_Line("i do something");
            --here code like
            --Horribly_Complicated_Recursive_Function(x,y);
         end Uno;
      or
         terminate;
      end select;
   end loop;
end A_Task;

begin --corpo genitore
   A_Task.Uno;
end Sempliced2;
------------------------------------------------

Speliced2 call the task entry uno.
now how Speliced2 can terminate the execution of the entry "uno" before
the
end of the call (es. time-out)?




^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: task time-out&abort
  2005-06-23 15:26 ` e.coli
@ 2005-06-23 17:01   ` e.coli
  2005-06-24 11:42     ` Marius Amado Alves
  2005-06-29 20:52   ` Robert A Duff
  1 sibling, 1 reply; 13+ messages in thread
From: e.coli @ 2005-06-23 17:01 UTC (permalink / raw)


> Speliced2 call the task entry uno.
> now how Speliced2 can terminate the execution of the entry "uno" before
> the
> end of the call (es. time-out)?

My goal is that the calling process can abort the call after x second
if the computation of the entry take too much time.

thanks




^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: task time-out&abort
  2005-06-23 17:01   ` e.coli
@ 2005-06-24 11:42     ` Marius Amado Alves
  2005-06-28 21:31       ` Robert A Duff
  0 siblings, 1 reply; 13+ messages in thread
From: Marius Amado Alves @ 2005-06-24 11:42 UTC (permalink / raw)
  To: comp.lang.ada

> My goal is that the calling process can abort the call after x second
> if the computation of the entry take too much time.

Curiously enough on 2001 I wrote this for an Ada-Europe workshop on 
exceptions:

<<
The time-out situation is so common that perhaps it deserves a special
device in a future Ada:

   begin
     ...
   end in 10.0; -- end in 10 seconds, or raise Time_Out
   exception
     when Time_Out => ...
 >>
(http://www.liacc.up.pt/~maa/files/ehada1.pdf)

Unfortunately it didn't make it and the implementation was left as an 
exercise.




^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: task time-out&abort
  2005-06-24 11:42     ` Marius Amado Alves
@ 2005-06-28 21:31       ` Robert A Duff
  2005-06-29  0:32         ` Marius Amado Alves
  0 siblings, 1 reply; 13+ messages in thread
From: Robert A Duff @ 2005-06-28 21:31 UTC (permalink / raw)


Marius Amado Alves <amado.alves@netcabo.pt> writes:

> > My goal is that the calling process can abort the call after x second
> > if the computation of the entry take too much time.
> 
> Curiously enough on 2001 I wrote this for an Ada-Europe workshop on
> exceptions:
> 
> <<
> The time-out situation is so common that perhaps it deserves a special
> device in a future Ada:
> 
>    begin
>      ...
>    end in 10.0; -- end in 10 seconds, or raise Time_Out
>    exception
>      when Time_Out => ...
>  >>
> (http://www.liacc.up.pt/~maa/files/ehada1.pdf)

How is this better than ATC (select-then-abort) in Ada 95?

Note that dynamically nested time-out regions won't work
very well in the above.  You need a distinct new exception
for each time-out, and you need to prevent hijacking of the
exception.

- Bob



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: task time-out&abort
  2005-06-28 21:31       ` Robert A Duff
@ 2005-06-29  0:32         ` Marius Amado Alves
  0 siblings, 0 replies; 13+ messages in thread
From: Marius Amado Alves @ 2005-06-29  0:32 UTC (permalink / raw)
  To: comp.lang.ada


On 28 Jun 2005, at 22:31, Robert A Duff wrote:

> Marius Amado Alves <amado.alves@netcabo.pt> writes:
>
>>> My goal is that the calling process can abort the call after x second
>>> if the computation of the entry take too much time.
>>
>> Curiously enough on 2001 I wrote this for an Ada-Europe workshop on
>> exceptions:
>>
>> <<
>> The time-out situation is so common that perhaps it deserves a special
>> device in a future Ada:
>>
>>    begin
>>      ...
>>    end in 10.0; -- end in 10 seconds, or raise Time_Out
>>    exception
>>      when Time_Out => ...
>>>>
>> (http://www.liacc.up.pt/~maa/files/ehada1.pdf)
>
> How is this better than ATC (select-then-abort) in Ada 95?
>
> Note that dynamically nested time-out regions won't work
> very well in the above.  You need a distinct new exception
> for each time-out, and you need to prevent hijacking of the
> exception.

Sure. Indeed I seem to remember that a major conclusion of the workshop 
was that ATC in Ada 95 was indeed a very good thing or at least good 
enough and this was in great part responsible for dropping most of the 
proposals for extension. Anyway, the above was just a (drafty like 
hell) specific idiom for the time-out situation, and for 'leaf' parts 
of the program. Even so, together with another proposal I made in the 
paper, namely that on the handler you could inspect where the exception 
came from, it could work also for dynamic scopes. But as indicated this 
is completely academic now.




^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: task time-out&abort
  2005-06-23 15:26 ` e.coli
  2005-06-23 17:01   ` e.coli
@ 2005-06-29 20:52   ` Robert A Duff
  2005-07-18 16:11     ` Robert I. Eachus
  1 sibling, 1 reply; 13+ messages in thread
From: Robert A Duff @ 2005-06-29 20:52 UTC (permalink / raw)


"e.coli" <maurizio.ferracini@gmail.com> writes:

> e.coli ha scritto:
> > here the code...
> 
> 
> i have this simple code...
> ------------------------------------
>   with Ada.Text_Io;
> 
> procedure Sempliced2 is
> 
>    task A_Task is
>       entry Uno;
>    end A_Task;
> 
>    task body A_Task is
>    begin
>       loop
>          select
>          accept Uno do
>             Ada.Text_Io.Put_Line("i do something");
>             --here code like
>             --Horribly_Complicated_Recursive_Function(x,y);
>          end Uno;
>       or
>          terminate;
>       end select;
>    end loop;
> end A_Task;
> 
> begin --corpo genitore
>    A_Task.Uno;
> end Sempliced2;
> ------------------------------------------------
> 
> Speliced2 call the task entry uno.
> now how Speliced2 can terminate the execution of the entry "uno" before
> the
> end of the call (es. time-out)?

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.

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.

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.

I think there are some examples in the Ada 95 Rationale.

- Bob



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: task time-out&abort
  2005-06-29 20:52   ` Robert A Duff
@ 2005-07-18 16:11     ` Robert I. Eachus
  0 siblings, 0 replies; 13+ messages in thread
From: Robert I. Eachus @ 2005-07-18 16:11 UTC (permalink / raw)


(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.




^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2005-07-18 16:11 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
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 is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox