comp.lang.ada
 help / color / mirror / Atom feed
* Freezing a task
@ 2011-11-17 15:33 Rego, P.
  2011-11-17 16:00 ` Simon Wright
                   ` (4 more replies)
  0 siblings, 5 replies; 24+ messages in thread
From: Rego, P. @ 2011-11-17 15:33 UTC (permalink / raw)


Is is possible to freeze a task?

I mean, if I have a task

task body My_Task is
begin 
  accept Start;
  loop
    Put ("1");
    Put ("2");
    Put ("3");
    ...
    Put ("n");
  end loop;
end My_Task;

is there a way that I can "freeze" the task in its current state? If, for instance, the execution finished executing Put ("2");, how can I freeze it and later I can turn it to continue? I want to provoque a freeze from outside the task, and also from outside, order it to continue.

I could sure implement, if I had the spec like

type State_Type is
  (RUN,
   FROZEN);

task type My_Task (State : State_Type) is
   entry Start;
end My_Task;
--

the body:

task body My_Task is
begin 
  accept Start;
  loop
    Put ("1");
    Put ("2");
    Put ("3");
    ...
    Put ("n");

    loop 
     if State = RUN then exit; end if;
    end loop;
  end loop;
end My_Task;

but it would not be the case because I had to wait for the nth Put instruction line (i.e., the task would not be actually frozen, because the inside loop would be running).

And T.E.D. from stackoverflow suggested me something that I could infer as

task type My_Task (Start : Start_Type) is 
   entry Start;
   entry Run;
end My_Task
--
task body My_Task is
begin 
  accept Start;
  loop
    Put ("1");
    Put ("2");
    Put ("3");
    ...
    Put ("n");

    if State = FROZEN then 
       accept Run;
       State := RUN;
    end if;
  end loop;
end My_Task;

Is there a more elegant way to do this? Maybe some procedure My_Task.FreezeNow in a unknown (by me) package? Thanks



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

* Re: Freezing a task
  2011-11-17 15:33 Freezing a task Rego, P.
@ 2011-11-17 16:00 ` Simon Wright
  2011-11-17 16:22   ` Dmitry A. Kazakov
  2011-11-17 16:00 ` Dmitry A. Kazakov
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 24+ messages in thread
From: Simon Wright @ 2011-11-17 16:00 UTC (permalink / raw)


"Rego, P." <pvrego@gmail.com> writes:

> Is there a more elegant way to do this? Maybe some procedure
> My_Task.FreezeNow in a unknown (by me) package? Thanks

Well, you could do it in the debugger :-)

Programmatically, no. Your choices for inter-task comms are (a) the
rendezvous, (b) polling some shared resource (eg a protected object),
(c) something using sockets.

Or you could unilaterally abort the task, which would be the end of it.

For (a), maybe something like

loop
   select
      accept Pause;
      accept Continue;
   else
      null;
   end select;
   --  do stuff
end loop;



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

* Re: Freezing a task
  2011-11-17 15:33 Freezing a task Rego, P.
  2011-11-17 16:00 ` Simon Wright
@ 2011-11-17 16:00 ` Dmitry A. Kazakov
  2011-11-17 16:53   ` stefan-lucks
  2011-11-17 17:13 ` Adam Beneschan
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 24+ messages in thread
From: Dmitry A. Kazakov @ 2011-11-17 16:00 UTC (permalink / raw)


On Thu, 17 Nov 2011 07:33:24 -0800 (PST), Rego, P. wrote:

> Is is possible to freeze a task?

Yes, by

1. an entry call to another task or a protected object;

2. executing a select or accept statement.

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



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

* Re: Freezing a task
  2011-11-17 16:00 ` Simon Wright
@ 2011-11-17 16:22   ` Dmitry A. Kazakov
  2011-11-17 16:53     ` Dmitry A. Kazakov
                       ` (2 more replies)
  0 siblings, 3 replies; 24+ messages in thread
From: Dmitry A. Kazakov @ 2011-11-17 16:22 UTC (permalink / raw)


On Thu, 17 Nov 2011 16:00:17 +0000, Simon Wright wrote:

> "Rego, P." <pvrego@gmail.com> writes:
> 
>> Is there a more elegant way to do this? Maybe some procedure
>> My_Task.FreezeNow in a unknown (by me) package? Thanks
> 
> Well, you could do it in the debugger :-)
> 
> Programmatically, no. Your choices for inter-task comms are (a) the
> rendezvous, (b) polling some shared resource (eg a protected object),
> (c) something using sockets.
> 
> Or you could unilaterally abort the task, which would be the end of it.
> 
> For (a), maybe something like
> 
> loop
>    select
>       accept Pause;
>       accept Continue;
>    else
>       null;
>    end select;
>    --  do stuff
> end loop;

If using select statement for accepting entry calls then:

   Paused : Boolean := False;
begin
   loop
      if Paused then
         accept Release;
         Paused := False;
      else
         select
            accept Pause;
            Paused := True;
         else
            ... -- Do stuff
         end select;
      end if;
   end loop;

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



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

* Re: Freezing a task
  2011-11-17 16:22   ` Dmitry A. Kazakov
@ 2011-11-17 16:53     ` Dmitry A. Kazakov
  2011-11-17 18:27     ` Simon Wright
  2011-11-18  1:23     ` Rego, P.
  2 siblings, 0 replies; 24+ messages in thread
From: Dmitry A. Kazakov @ 2011-11-17 16:53 UTC (permalink / raw)


On Thu, 17 Nov 2011 17:22:57 +0100, Dmitry A. Kazakov wrote:

>    Paused : Boolean := False;
> begin
>    loop
>       if Paused then
>          accept Release;
>          Paused := False;
>       else
>          select
>             accept Pause;
>             Paused := True;
>          else
>             ... -- Do stuff
>          end select;
>       end if;
>    end loop;

P.S. there is a deadlock in above if improperly used from outside. It is
simple to fix.

It is worth to note that one of the rationales behind protected objects
introduced in Ada 95, was to ease things like above. The same done with a
protected object would be simpler, safer and reusable (within the task)
too.

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



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

* Re: Freezing a task
  2011-11-17 16:00 ` Dmitry A. Kazakov
@ 2011-11-17 16:53   ` stefan-lucks
  2011-11-17 17:08     ` Dmitry A. Kazakov
  0 siblings, 1 reply; 24+ messages in thread
From: stefan-lucks @ 2011-11-17 16:53 UTC (permalink / raw)


On Thu, 17 Nov 2011, Dmitry A. Kazakov wrote:

> On Thu, 17 Nov 2011 07:33:24 -0800 (PST), Rego, P. wrote:
> 
> > Is is possible to freeze a task?
> 
> Yes, by
> 
> 1. an entry call to another task or a protected object;
> 
> 2. executing a select or accept statement.

What do you really want? Why do you want a task to freeze? 

If you just want to freeze a task to ensure another more important task 
isn't slowed down (and unfreeze when the other task is done) a MUCH more 
elegant way to do this is to use task priorities.


-- 
---- Stefan.Lucks (at) uni-weimar.de, University of Weimar, Germany  ----
    <http://www.uni-weimar.de/cms/medien/mediensicherheit/home.html>
------  I  love  the  taste  of  Cryptanalysis  in  the  morning!  ------




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

* Re: Freezing a task
  2011-11-17 16:53   ` stefan-lucks
@ 2011-11-17 17:08     ` Dmitry A. Kazakov
  0 siblings, 0 replies; 24+ messages in thread
From: Dmitry A. Kazakov @ 2011-11-17 17:08 UTC (permalink / raw)


On Thu, 17 Nov 2011 17:53:46 +0100, stefan-lucks@see-the.signature wrote:

> If you just want to freeze a task to ensure another more important task 
> isn't slowed down (and unfreeze when the other task is done) a MUCH more 
> elegant way to do this is to use task priorities.

Maybe, however it would not work as the given example does I/O.

Unless you have access to very high level OS priorities (which you normally
don't) you won't be able to stop the system services, drivers and interrupt
routines doing I/O the behalf of the task. Not that you really wanted it
anyway...

IMO, in probably 90% all cases playing with priorities is a bad idea. The
rest 10% require a very careful upfront analysis.

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



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

* Re: Freezing a task
  2011-11-17 15:33 Freezing a task Rego, P.
  2011-11-17 16:00 ` Simon Wright
  2011-11-17 16:00 ` Dmitry A. Kazakov
@ 2011-11-17 17:13 ` Adam Beneschan
  2011-11-17 18:01   ` AdaMagica
  2011-11-18  1:22   ` Rego, P.
  2011-11-17 17:34 ` Jeffrey Carter
  2011-11-18  7:24 ` anon
  4 siblings, 2 replies; 24+ messages in thread
From: Adam Beneschan @ 2011-11-17 17:13 UTC (permalink / raw)


On Nov 17, 7:33 am, "Rego, P." <pvr...@gmail.com> wrote:
> Is is possible to freeze a task?
>
> I mean, if I have a task
>
> task body My_Task is
> begin
>   accept Start;
>   loop
>     Put ("1");
>     Put ("2");
>     Put ("3");
>     ...
>     Put ("n");
>   end loop;
> end My_Task;
>
> is there a way that I can "freeze" the task in its current state? If, for instance, the execution finished executing Put ("2");, how can I freeze it and later I can turn it to continue? I want to provoque a freeze from outside the task, and also from outside, order it to continue.
>
> I could sure implement, if I had the spec like
>
> type State_Type is
>   (RUN,
>    FROZEN);
>
> task type My_Task (State : State_Type) is
>    entry Start;
> end My_Task;
> --
>
> the body:
>
> task body My_Task is
> begin
>   accept Start;
>   loop
>     Put ("1");
>     Put ("2");
>     Put ("3");
>     ...
>     Put ("n");
>
>     loop
>      if State = RUN then exit; end if;
>     end loop;
>   end loop;
> end My_Task;
>
> but it would not be the case because I had to wait for the nth Put instruction line (i.e., the task would not be actually frozen, because the inside loop would be running).
>
> And T.E.D. from stackoverflow suggested me something that I could infer as
>
> task type My_Task (Start : Start_Type) is
>    entry Start;
>    entry Run;
> end My_Task
> --
> task body My_Task is
> begin
>   accept Start;
>   loop
>     Put ("1");
>     Put ("2");
>     Put ("3");
>     ...
>     Put ("n");
>
>     if State = FROZEN then
>        accept Run;
>        State := RUN;
>     end if;
>   end loop;
> end My_Task;
>
> Is there a more elegant way to do this? Maybe some procedure My_Task.FreezeNow in a unknown (by me) package? Thanks

Aside from the other suggestions, you might want to look into
Ada.Synchronous_Task_Control and Ada.Asynchronous_Task_Control.  I'm
not really clear on what you're trying to accomplish, so it's hard for
me to say whether those are appropriate solutions for you.  I think
that the other methods that have been suggested--an entry call on
another task or on a protected object, or an ACCEPT statement--would
be preferable if they get the job done.

                               -- Adam



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

* Re: Freezing a task
  2011-11-17 15:33 Freezing a task Rego, P.
                   ` (2 preceding siblings ...)
  2011-11-17 17:13 ` Adam Beneschan
@ 2011-11-17 17:34 ` Jeffrey Carter
  2011-11-18  1:34   ` Rego, P.
  2011-11-18  7:24 ` anon
  4 siblings, 1 reply; 24+ messages in thread
From: Jeffrey Carter @ 2011-11-17 17:34 UTC (permalink / raw)


On 11/17/2011 08:33 AM, Rego, P. wrote:
>
> is there a way that I can "freeze" the task in its current state? If, for
> instance, the execution finished executing Put ("2");, how can I freeze it
> and later I can turn it to continue? I want to provoque a freeze from outside
> the task, and also from outside, order it to continue.

The real question is "What is the problem you're trying to solve?" What you're 
asking about is a possible solution to some problem. If we know what that 
problem is, we can likely provide a suitable solution. With only the possible 
solution, all we can tell you is it won't work. Ada tasks are self scheduling; 
you can't schedule them externally.

-- 
Jeff Carter
"You can never forget too much about C++."
115



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

* Re: Freezing a task
  2011-11-17 17:13 ` Adam Beneschan
@ 2011-11-17 18:01   ` AdaMagica
  2011-11-18  1:22   ` Rego, P.
  1 sibling, 0 replies; 24+ messages in thread
From: AdaMagica @ 2011-11-17 18:01 UTC (permalink / raw)


> Aside from the other suggestions, you might want to look into
> Ada.Synchronous_Task_Control and Ada.Asynchronous_Task_Control.

Synch. might do the job, asynch is (for GNAT) only implemented on bare
boards.



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

* Re: Freezing a task
  2011-11-17 16:22   ` Dmitry A. Kazakov
  2011-11-17 16:53     ` Dmitry A. Kazakov
@ 2011-11-17 18:27     ` Simon Wright
  2011-11-18  1:23     ` Rego, P.
  2 siblings, 0 replies; 24+ messages in thread
From: Simon Wright @ 2011-11-17 18:27 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:

> On Thu, 17 Nov 2011 16:00:17 +0000, Simon Wright wrote:
>
>> "Rego, P." <pvrego@gmail.com> writes:
>> 
>>> Is there a more elegant way to do this? Maybe some procedure
>>> My_Task.FreezeNow in a unknown (by me) package? Thanks
>> 
>> Well, you could do it in the debugger :-)
>> 
>> Programmatically, no. Your choices for inter-task comms are (a) the
>> rendezvous, (b) polling some shared resource (eg a protected object),
>> (c) something using sockets.
>> 
>> Or you could unilaterally abort the task, which would be the end of it.
>> 
>> For (a), maybe something like
>> 
>> loop
>>    select
>>       accept Pause;
>>       accept Continue;
>>    else
>>       null;
>>    end select;
>>    --  do stuff
>> end loop;
>
> If using select statement for accepting entry calls then:
>
>    Paused : Boolean := False;
> begin
>    loop
>       if Paused then
>          accept Release;
>          Paused := False;
>       else
>          select
>             accept Pause;
>             Paused := True;
>          else
>             ... -- Do stuff
>          end select;
>       end if;
>    end loop;

OK, but mine works too as long as you treat it with care! (BTW I agree
about the protected object being a better choice)



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

* Re: Freezing a task
  2011-11-17 17:13 ` Adam Beneschan
  2011-11-17 18:01   ` AdaMagica
@ 2011-11-18  1:22   ` Rego, P.
  1 sibling, 0 replies; 24+ messages in thread
From: Rego, P. @ 2011-11-18  1:22 UTC (permalink / raw)


> Aside from the other suggestions, you might want to look into
> Ada.Synchronous_Task_Control and Ada.Asynchronous_Task_Control.

I shall go to take a look on it. Thank you.




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

* Re: Freezing a task
  2011-11-17 16:22   ` Dmitry A. Kazakov
  2011-11-17 16:53     ` Dmitry A. Kazakov
  2011-11-17 18:27     ` Simon Wright
@ 2011-11-18  1:23     ` Rego, P.
  2011-11-18  6:04       ` Jeffrey Carter
  2011-11-18  8:47       ` Dmitry A. Kazakov
  2 siblings, 2 replies; 24+ messages in thread
From: Rego, P. @ 2011-11-18  1:23 UTC (permalink / raw)
  Cc: mailbox

>    Paused : Boolean := False;
> begin
>    loop
>       if Paused then
>          accept Release;
>          Paused := False;
>       else
>          select
>             accept Pause;
>             Paused := True;
>          else
>             ... -- Do stuff
>          end select;
>       end if;
>    end loop;

So I can use

Paused : Boolean := False;
begin
    accept Start;
    loop
       if Paused then
          accept Release;
          Paused := False;
       else
          select
             accept Pause;
             Paused := True;
          else
             ... -- Do stuff
          end select;
       end if;
    end loop;

and if I would want to add an abort entry? What should I do? 



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

* Re: Freezing a task
  2011-11-17 17:34 ` Jeffrey Carter
@ 2011-11-18  1:34   ` Rego, P.
  2011-11-18  8:56     ` Dmitry A. Kazakov
  0 siblings, 1 reply; 24+ messages in thread
From: Rego, P. @ 2011-11-18  1:34 UTC (permalink / raw)


Well, answering also Jeff, Adam and Stefan, there are some bots which are shared by some tasks, and each task controls just one subsystem reciprocally (i.e. this one is controlled at one timeslot by just one task), but other tasks can "steal" the thread, so they can assume the control over that ones. But each task has also a different eurystics, so when it assumes a bot, it behaves different, but I want them to be restored to any other previous controllers. Due to this I needed to "pause" that task. I guess Dmitry answer could be used very well for this (but also Simon's).



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

* Re: Freezing a task
  2011-11-18  1:23     ` Rego, P.
@ 2011-11-18  6:04       ` Jeffrey Carter
  2011-11-18  8:47       ` Dmitry A. Kazakov
  1 sibling, 0 replies; 24+ messages in thread
From: Jeffrey Carter @ 2011-11-18  6:04 UTC (permalink / raw)


On 11/17/2011 06:23 PM, Rego, P. wrote:
>
> So I can use
>
> Paused : Boolean := False;
> begin
>      accept Start;
>      loop
>         if Paused then
>            accept Release;
>            Paused := False;
>         else
>            select
>               accept Pause;
>               Paused := True;
>            else
>               ... -- Do stuff
>            end select;
>         end if;
>      end loop;
>
> and if I would want to add an abort entry? What should I do?

Depends on when you want to be able to stop the task. I'd guess

select
    accept Pause;
    Paused := True;
or
    accept Stop;

    exit;
else
    -- Do stuff.
end select;

"abort" is a reserved word, so it can't be the name of the entry. A protected 
object seems cleaner, though:

protected Control is
    procedure Process;
    -- Instruct the task to start processing, or to resume processing after
    -- being paused.

    procedure Stop;
    -- Tell the task to terminate.

    procedure Pause;
    -- Tell the task to pause processing.

    entry Get (Stop : out Boolean);
    -- Used by the task to wait until it should do something.
    -- Stop will be True if the task should terminate; False if it should
    -- do stuff.
private -- Control
    ...
end Control;

task body T is
    Stop : Boolean;
begin -- T
    loop
       Control.Get (Stop => Stop);

       exit when Stop;

       -- Do stuff.
    end loop;
end T;

-- 
Jeff Carter
"You can never forget too much about C++."
115



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

* Re: Freezing a task
  2011-11-17 15:33 Freezing a task Rego, P.
                   ` (3 preceding siblings ...)
  2011-11-17 17:34 ` Jeffrey Carter
@ 2011-11-18  7:24 ` anon
  2011-11-18 22:25   ` Anh Vo
  2011-11-22  1:58   ` Rego, P.
  4 siblings, 2 replies; 24+ messages in thread
From: anon @ 2011-11-18  7:24 UTC (permalink / raw)


--
--  Complete Program
--

with Text_IO ;

procedure u is

  use Text_IO ;

  task type test is
      entry Start ;    -- initialize and start task
                       -- and task can die if parent stops

      entry Wait ;     -- Send task to sleep for a while 
                       -- and task can die if parent stops

      entry Continue ; -- wake up task
      entry Stop ;     -- stops and kill task
  end test ;


  task body test is

      Count : Integer ;
    begin
      --  Initialize task 
      Count := 0  ;
      Outer_Loop : loop 
        select
          --  start task
          accept Start ;
            Put_Line ( "Start" ) ;

            Main_Loop : loop 
              select

                --  pause task
                accept Wait ; 
                  Put_Line ( "Wait" ) ;
                  New_Line ;

                  select

                    --  sofware wake up task
                    accept Continue ;
                      Put_Line ( "Continue" ) ;

                  --  software exit while in wait mode
                  or
                    accept Stop ; 
                      Put_Line ( "Stop" ) ;
                      exit Outer_Loop ;

                  --  exit if parent fails while in wait mode
                  or 
                    terminate ;
                  end select ;

              --  software exit (abort) while in normal 
              --  execution mode
              or 
                accept Stop ; 
                    Put_Line ( "Stop" ) ;
                    exit Outer_Loop ;

              else
                -- - - - - - - - - - - --
                --  Main Tasking Code  --
                -- - - - - - - - - - - --
                Put ( "Testing" ) ;
                Put ( Integer'Image ( Count ) ) ;        
                New_Line ;
                Count := Count + 1 ;
              end select ;
          end loop Main_Loop ;

        --  exit if parent fails
        or
          terminate ;
        end select ;
      end loop Outer_Loop ;
      Put_Line ( "Task has Terminated" ) ;
    end test ;

 testing_task      : test ;

begin
  Put_Line ( "Start Tasking" ) ;
  New_Line ;
  --
  testing_task.Start ;
  delay ( 0.01 ) ;
  testing_task.Wait ;
  delay ( 1.0 ) ;
  testing_task.Continue ; 
  delay ( 0.01 ) ;
  testing_task.Wait ;
  --
  delay ( 1.0 ) ;
  testing_task.Stop ; 
  delay ( 0.5 ) ;
  New_Line ;
end u ;


In <32992849.648.1321544004241.JavaMail.geo-discussion-forums@vbmh5>, "Rego, P." <pvrego@gmail.com> writes:
>Is is possible to freeze a task?
>
>I mean, if I have a task
>
>task body My_Task is
>begin=20
>  accept Start;
>  loop
>    Put ("1");
>    Put ("2");
>    Put ("3");
>    ...
>    Put ("n");
>  end loop;
>end My_Task;
>
>is there a way that I can "freeze" the task in its current state? If, for i=
>nstance, the execution finished executing Put ("2");, how can I freeze it a=
>nd later I can turn it to continue? I want to provoque a freeze from outsid=
>e the task, and also from outside, order it to continue.
>
>I could sure implement, if I had the spec like
>
>type State_Type is
>  (RUN,
>   FROZEN);
>
>task type My_Task (State : State_Type) is
>   entry Start;
>end My_Task;
>--
>
>the body:
>
>task body My_Task is
>begin=20
>  accept Start;
>  loop
>    Put ("1");
>    Put ("2");
>    Put ("3");
>    ...
>    Put ("n");
>
>    loop=20
>     if State =3D RUN then exit; end if;
>    end loop;
>  end loop;
>end My_Task;
>
>but it would not be the case because I had to wait for the nth Put instruct=
>ion line (i.e., the task would not be actually frozen, because the inside l=
>oop would be running).
>
>And T.E.D. from stackoverflow suggested me something that I could infer as
>
>task type My_Task (Start : Start_Type) is=20
>   entry Start;
>   entry Run;
>end My_Task
>--
>task body My_Task is
>begin=20
>  accept Start;
>  loop
>    Put ("1");
>    Put ("2");
>    Put ("3");
>    ...
>    Put ("n");
>
>    if State =3D FROZEN then=20
>       accept Run;
>       State :=3D RUN;
>    end if;
>  end loop;
>end My_Task;
>
>Is there a more elegant way to do this? Maybe some procedure My_Task.Freeze=
>Now in a unknown (by me) package? Thanks




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

* Re: Freezing a task
  2011-11-18  1:23     ` Rego, P.
  2011-11-18  6:04       ` Jeffrey Carter
@ 2011-11-18  8:47       ` Dmitry A. Kazakov
  2011-11-18 10:05         ` Simon Wright
  1 sibling, 1 reply; 24+ messages in thread
From: Dmitry A. Kazakov @ 2011-11-18  8:47 UTC (permalink / raw)


On Thu, 17 Nov 2011 17:23:55 -0800 (PST), Rego, P. wrote:

>>    Paused : Boolean := False;
>> begin
>>    loop
>>       if Paused then
>>          accept Release;
>>          Paused := False;
>>       else
>>          select
>>             accept Pause;
>>             Paused := True;
>>          else
>>             ... -- Do stuff
>>          end select;
>>       end if;
>>    end loop;
> 
> So I can use
> 
> Paused : Boolean := False;
> begin
>     accept Start;
>     loop
>        if Paused then
>           accept Release;
>           Paused := False;
>        else
>           select
>              accept Pause;
>              Paused := True;
>           else
>              ... -- Do stuff
>           end select;
>        end if;
>     end loop;
> 
> and if I would want to add an abort entry? What should I do?

Note that the above has a deadlock when you call to Pause or Release twice.
It is easy to correct, but a protected object solution would be more
robust. See the Jeffrey's response, however, I would use an exception
rather than output parameter:

Pending_Abort : exception;
protected type Control is
   procedure Process;
   procedure Pause;
   procedure Stop;
   entry Get;
private
   Paused : Boolean := False;
   Exiting : Boolean := False;
end Control;

protected body Control is
   procedure Process is
   begin
       Paused := False;
   end Process;
   procedure Pause is
   begin
       Paused := True;
   end Pause;
   procedure Stop is
       Exiting := True;
   end Stop;
   entry Get when not Paused or Exiting is
   begin
       if Exiting then
         raise Pending_Abort;
      end if;
   end Get;
private
   Paused : Boolean := False;
   Exiting : Boolean := False;
end Control;

task body T is
begin
    loop
       Control_Instance.Get;
       ... -- Do stuff
       Control_Instance.Get;
       ... -- Do other stuff
       Control_Instance.Get;
       ... -- Do yet another stuff
    end loop;
exception
   when Pending_Abort =>
        null;
end T;

You don't need Start entry of the task. Just make Paused initially true.

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



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

* Re: Freezing a task
  2011-11-18  1:34   ` Rego, P.
@ 2011-11-18  8:56     ` Dmitry A. Kazakov
  0 siblings, 0 replies; 24+ messages in thread
From: Dmitry A. Kazakov @ 2011-11-18  8:56 UTC (permalink / raw)


On Thu, 17 Nov 2011 17:34:48 -0800 (PST), Rego, P. wrote:

> Well, answering also Jeff, Adam and Stefan, there are some bots which are
> shared by some tasks, and each task controls just one subsystem
> reciprocally (i.e. this one is controlled at one timeslot by just one
> task), but other tasks can "steal" the thread, so they can assume the
> control over that ones.

This is what rendezvous are for. If the task A and the task B must
cooperatively do some stuff (= control a bot), they just engage a
rendezvous and perform that stuff upon the rendezvous. That would
effectively block one of them.

P.S. I don't understand this design. Why do not you have a pool of tasks
and assign a free one for each operation to be performed on the bot? Once
completed the operation, the task returns to the pool.

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



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

* Re: Freezing a task
  2011-11-18  8:47       ` Dmitry A. Kazakov
@ 2011-11-18 10:05         ` Simon Wright
  2011-11-18 11:41           ` Georg Bauhaus
  0 siblings, 1 reply; 24+ messages in thread
From: Simon Wright @ 2011-11-18 10:05 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:

> however, I would use an exception rather than output parameter

I like that. Will give it strong consideration for a design update (of
course, it wouldn't do for a SPARK implementation; personally I'd like
to see SPARK allow provably-handled exceptions (though I suspect the
problem is with "provably")).



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

* Re: Freezing a task
  2011-11-18 10:05         ` Simon Wright
@ 2011-11-18 11:41           ` Georg Bauhaus
  2011-11-18 13:42             ` Dmitry A. Kazakov
  0 siblings, 1 reply; 24+ messages in thread
From: Georg Bauhaus @ 2011-11-18 11:41 UTC (permalink / raw)


On 18.11.11 11:05, Simon Wright wrote:
> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:
> 
>> however, I would use an exception rather than output parameter
> 
> I like that. Will give it strong consideration for a design update (of
> course, it wouldn't do for a SPARK implementation; personally I'd like
> to see SPARK allow provably-handled exceptions (though I suspect the
> problem is with "provably")).

In case I want an interrupt to stop (and release) the task,
will an exception, such as Pending_Abort from the example,
work? Because, IIUC, when the protected procedure handling the
interrupt raises Pending_Abort, then this has no effect
(as the procedure is a handler, LRM C.3(7)). Is this correct?

Maybe the handler procedure might just adjust the status of
the object so as to take note of the interrupt.
When the task then calls an entry such as Get from the example,
and the entry raises an exception, it will have an effect. But then,
this will interrupt the task only later...



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

* Re: Freezing a task
  2011-11-18 11:41           ` Georg Bauhaus
@ 2011-11-18 13:42             ` Dmitry A. Kazakov
  0 siblings, 0 replies; 24+ messages in thread
From: Dmitry A. Kazakov @ 2011-11-18 13:42 UTC (permalink / raw)


On Fri, 18 Nov 2011 12:41:41 +0100, Georg Bauhaus wrote:

> On 18.11.11 11:05, Simon Wright wrote:
>> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:
>> 
>>> however, I would use an exception rather than output parameter
>> 
>> I like that. Will give it strong consideration for a design update (of
>> course, it wouldn't do for a SPARK implementation; personally I'd like
>> to see SPARK allow provably-handled exceptions (though I suspect the
>> problem is with "provably")).
> 
> In case I want an interrupt to stop (and release) the task,
> will an exception, such as Pending_Abort from the example,
> work?

Since the entry point Get is to be called on the context of a task,
Pending_Abort will never propagate on the context of an interrupt.

> When the task then calls an entry such as Get from the example,
> and the entry raises an exception, it will have an effect. But then,
> this will interrupt the task only later...

This is exactly the implementation. BTW this is also the case for the
terminate alternative, which is accepted when the task is ready to accept
it.

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



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

* Re: Freezing a task
  2011-11-18  7:24 ` anon
@ 2011-11-18 22:25   ` Anh Vo
  2011-11-19  7:37     ` anon
  2011-11-22  1:58   ` Rego, P.
  1 sibling, 1 reply; 24+ messages in thread
From: Anh Vo @ 2011-11-18 22:25 UTC (permalink / raw)


On Nov 17, 11:24 pm, a...@att.net wrote:
> --
> --  Complete Program
> --
>
> with Text_IO ;
>
> procedure u is
>
>   use Text_IO ;
>
>   task type test is
>       entry Start ;    -- initialize and start task
>                        -- and task can die if parent stops
>
>       entry Wait ;     -- Send task to sleep for a while
>                        -- and task can die if parent stops
>
>       entry Continue ; -- wake up task
>       entry Stop ;     -- stops and kill task
>   end test ;
>
>   task body test is
>
>       Count : Integer ;
>     begin
>       --  Initialize task
>       Count := 0  ;
>       Outer_Loop : loop
>         select
>           --  start task
>           accept Start ;
>             Put_Line ( "Start" ) ;
>
>             Main_Loop : loop
>               select
>
>                 --  pause task
>                 accept Wait ;
>                   Put_Line ( "Wait" ) ;
>                   New_Line ;
>
>                   select
>
>                     --  sofware wake up task
>                     accept Continue ;
>                       Put_Line ( "Continue" ) ;
>
>                   --  software exit while in wait mode
>                   or
>                     accept Stop ;
>                       Put_Line ( "Stop" ) ;
>                       exit Outer_Loop ;
>
>                   --  exit if parent fails while in wait mode
>                   or
>                     terminate ;
>                   end select ;
>
>               --  software exit (abort) while in normal
>               --  execution mode
>               or
>                 accept Stop ;
>                     Put_Line ( "Stop" ) ;
>                     exit Outer_Loop ;
>
>               else
>                 -- - - - - - - - - - - --
>                 --  Main Tasking Code  --
>                 -- - - - - - - - - - - --
>                 Put ( "Testing" ) ;
>                 Put ( Integer'Image ( Count ) ) ;
>                 New_Line ;
>                 Count := Count + 1 ;
>               end select ;
>           end loop Main_Loop ;
>
>         --  exit if parent fails
>         or
>           terminate ;
>         end select ;
>       end loop Outer_Loop ;
>       Put_Line ( "Task has Terminated" ) ;
>     end test ;
>
>  testing_task      : test ;
>
> begin
>   Put_Line ( "Start Tasking" ) ;
>   New_Line ;
>   --
>   testing_task.Start ;
>   delay ( 0.01 ) ;
>   testing_task.Wait ;
>   delay ( 1.0 ) ;
>   testing_task.Continue ;
>   delay ( 0.01 ) ;
>   testing_task.Wait ;
>   --
>   delay ( 1.0 ) ;
>   testing_task.Stop ;
>   delay ( 0.5 ) ;
>   New_Line ;
> end u ;

I am not sure what was meant by couple of annotated comments
mentioning parent fails. Normally, tasks are declared at library
level. Thus, they will terminate when the main program terminates. In
this particular example, the task will terminate when the main
procedure terminates.

Anh Vo



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

* Re: Freezing a task
  2011-11-18 22:25   ` Anh Vo
@ 2011-11-19  7:37     ` anon
  0 siblings, 0 replies; 24+ messages in thread
From: anon @ 2011-11-19  7:37 UTC (permalink / raw)


In some programming circles, the "main procedure" is also called the parent. 

And tasks without the "Terminate" statement some times will continue to 
execute, even when the parent aka "main procedure" dies. One reason for 
the disliked "Abort" statement.

Two examples of tasks that do not contain "terminate" statement are 
servers and tasking device drivers. For the task to stop, these tasks 
must be setup to handle a "Stop" type of call to interrupt the process 
or another routine may have to use the "Abort" statement.

Of course, there always the "Ada.Synchronous_Task_Control but that's
a more involved process. And a fully functional version of the package 
Ada.Asynchronous_Task_Control is not supply in the general release 
of GNAT version of Ada.

In my example the one thing I did not include was the single to 
multiple layers of exceptions that could be added.




In <cfdf14ce-1304-4c52-a8ec-3cfbd51669ee@g21g2000yqc.googlegroups.com>, Anh Vo <anhvofrcaus@gmail.com> writes:
>On Nov 17, 11:24=A0pm, a...@att.net wrote:
>> --
>> -- =A0Complete Program
>> --
>>
>> with Text_IO ;
>>
>> procedure u is
>>
>> =A0 use Text_IO ;
>>
>> =A0 task type test is
>> =A0 =A0 =A0 entry Start ; =A0 =A0-- initialize and start task
>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0-- and task can die if par=
>ent stops
>>
>> =A0 =A0 =A0 entry Wait ; =A0 =A0 -- Send task to sleep for a while
>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0-- and task can die if par=
>ent stops
>>
>> =A0 =A0 =A0 entry Continue ; -- wake up task
>> =A0 =A0 =A0 entry Stop ; =A0 =A0 -- stops and kill task
>> =A0 end test ;
>>
>> =A0 task body test is
>>
>> =A0 =A0 =A0 Count : Integer ;
>> =A0 =A0 begin
>> =A0 =A0 =A0 -- =A0Initialize task
>> =A0 =A0 =A0 Count :=3D 0 =A0;
>> =A0 =A0 =A0 Outer_Loop : loop
>> =A0 =A0 =A0 =A0 select
>> =A0 =A0 =A0 =A0 =A0 -- =A0start task
>> =A0 =A0 =A0 =A0 =A0 accept Start ;
>> =A0 =A0 =A0 =A0 =A0 =A0 Put_Line ( "Start" ) ;
>>
>> =A0 =A0 =A0 =A0 =A0 =A0 Main_Loop : loop
>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 select
>>
>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 -- =A0pause task
>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 accept Wait ;
>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 Put_Line ( "Wait" ) ;
>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 New_Line ;
>>
>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 select
>>
>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 -- =A0sofware wake up task
>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 accept Continue ;
>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 Put_Line ( "Continue" ) ;
>>
>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 -- =A0software exit while in wait mod=
>e
>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 or
>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 accept Stop ;
>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 Put_Line ( "Stop" ) ;
>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 exit Outer_Loop ;
>>
>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 -- =A0exit if parent fails while in w=
>ait mode
>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 or
>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 terminate ;
>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 end select ;
>>
>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 -- =A0software exit (abort) while in normal
>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 -- =A0execution mode
>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 or
>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 accept Stop ;
>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 Put_Line ( "Stop" ) ;
>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 exit Outer_Loop ;
>>
>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 else
>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 -- - - - - - - - - - - --
>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 -- =A0Main Tasking Code =A0--
>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 -- - - - - - - - - - - --
>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 Put ( "Testing" ) ;
>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 Put ( Integer'Image ( Count ) ) ;
>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 New_Line ;
>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 Count :=3D Count + 1 ;
>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 end select ;
>> =A0 =A0 =A0 =A0 =A0 end loop Main_Loop ;
>>
>> =A0 =A0 =A0 =A0 -- =A0exit if parent fails
>> =A0 =A0 =A0 =A0 or
>> =A0 =A0 =A0 =A0 =A0 terminate ;
>> =A0 =A0 =A0 =A0 end select ;
>> =A0 =A0 =A0 end loop Outer_Loop ;
>> =A0 =A0 =A0 Put_Line ( "Task has Terminated" ) ;
>> =A0 =A0 end test ;
>>
>> =A0testing_task =A0 =A0 =A0: test ;
>>
>> begin
>> =A0 Put_Line ( "Start Tasking" ) ;
>> =A0 New_Line ;
>> =A0 --
>> =A0 testing_task.Start ;
>> =A0 delay ( 0.01 ) ;
>> =A0 testing_task.Wait ;
>> =A0 delay ( 1.0 ) ;
>> =A0 testing_task.Continue ;
>> =A0 delay ( 0.01 ) ;
>> =A0 testing_task.Wait ;
>> =A0 --
>> =A0 delay ( 1.0 ) ;
>> =A0 testing_task.Stop ;
>> =A0 delay ( 0.5 ) ;
>> =A0 New_Line ;
>> end u ;
>
>I am not sure what was meant by couple of annotated comments
>mentioning parent fails. Normally, tasks are declared at library
>level. Thus, they will terminate when the main program terminates. In
>this particular example, the task will terminate when the main
>procedure terminates.
>
>Anh Vo




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

* Re: Freezing a task
  2011-11-18  7:24 ` anon
  2011-11-18 22:25   ` Anh Vo
@ 2011-11-22  1:58   ` Rego, P.
  1 sibling, 0 replies; 24+ messages in thread
From: Rego, P. @ 2011-11-22  1:58 UTC (permalink / raw)
  Cc: anon

> --
> --  Complete Program
> --
> 
> with Text_IO ;
> 
> procedure u is
> 
>   use Text_IO ;
> 
>   task type test is
>       entry Start ;    -- initialize and start task
>                        -- and task can die if parent stops
> 
>       entry Wait ;     -- Send task to sleep for a while 
>                        -- and task can die if parent stops
> 
>       entry Continue ; -- wake up task
>       entry Stop ;     -- stops and kill task
>   end test ;
> 
> 
>   task body test is
> 
>       Count : Integer ;
>     begin
>       --  Initialize task 
>       Count := 0  ;
>       Outer_Loop : loop 
>         select
>           --  start task
>           accept Start ;
>             Put_Line ( "Start" ) ;
> 
>             Main_Loop : loop 
>               select
> 
>                 --  pause task
>                 accept Wait ; 
>                   Put_Line ( "Wait" ) ;
>                   New_Line ;
> 
>                   select
> 
>                     --  sofware wake up task
>                     accept Continue ;
>                       Put_Line ( "Continue" ) ;
> 
>                   --  software exit while in wait mode
>                   or
>                     accept Stop ; 
>                       Put_Line ( "Stop" ) ;
>                       exit Outer_Loop ;
> 
>                   --  exit if parent fails while in wait mode
>                   or 
>                     terminate ;
>                   end select ;
> 
>               --  software exit (abort) while in normal 
>               --  execution mode
>               or 
>                 accept Stop ; 
>                     Put_Line ( "Stop" ) ;
>                     exit Outer_Loop ;
> 
>               else
>                 -- - - - - - - - - - - --
>                 --  Main Tasking Code  --
>                 -- - - - - - - - - - - --
>                 Put ( "Testing" ) ;
>                 Put ( Integer'Image ( Count ) ) ;        
>                 New_Line ;
>                 Count := Count + 1 ;
>               end select ;
>           end loop Main_Loop ;
> 
>         --  exit if parent fails
>         or
>           terminate ;
>         end select ;
>       end loop Outer_Loop ;
>       Put_Line ( "Task has Terminated" ) ;
>     end test ;
> 
>  testing_task      : test ;
> 
> begin
>   Put_Line ( "Start Tasking" ) ;
>   New_Line ;
>   --
>   testing_task.Start ;
>   delay ( 0.01 ) ;
>   testing_task.Wait ;
>   delay ( 1.0 ) ;
>   testing_task.Continue ; 
>   delay ( 0.01 ) ;
>   testing_task.Wait ;
>   --
>   delay ( 1.0 ) ;
>   testing_task.Stop ; 
>   delay ( 0.5 ) ;
>   New_Line ;
> end u ;

I guess that's a very elegant way to implement it. Very thank you. 



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

end of thread, other threads:[~2011-11-22  1:58 UTC | newest]

Thread overview: 24+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-11-17 15:33 Freezing a task Rego, P.
2011-11-17 16:00 ` Simon Wright
2011-11-17 16:22   ` Dmitry A. Kazakov
2011-11-17 16:53     ` Dmitry A. Kazakov
2011-11-17 18:27     ` Simon Wright
2011-11-18  1:23     ` Rego, P.
2011-11-18  6:04       ` Jeffrey Carter
2011-11-18  8:47       ` Dmitry A. Kazakov
2011-11-18 10:05         ` Simon Wright
2011-11-18 11:41           ` Georg Bauhaus
2011-11-18 13:42             ` Dmitry A. Kazakov
2011-11-17 16:00 ` Dmitry A. Kazakov
2011-11-17 16:53   ` stefan-lucks
2011-11-17 17:08     ` Dmitry A. Kazakov
2011-11-17 17:13 ` Adam Beneschan
2011-11-17 18:01   ` AdaMagica
2011-11-18  1:22   ` Rego, P.
2011-11-17 17:34 ` Jeffrey Carter
2011-11-18  1:34   ` Rego, P.
2011-11-18  8:56     ` Dmitry A. Kazakov
2011-11-18  7:24 ` anon
2011-11-18 22:25   ` Anh Vo
2011-11-19  7:37     ` anon
2011-11-22  1:58   ` Rego, P.

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