comp.lang.ada
 help / color / mirror / Atom feed
* Rendezvous with select ... else and "or terminate" not possible - but how do I quit this task?
@ 2016-09-01 15:43 Some Dude
  2016-09-01 16:05 ` J-P. Rosen
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Some Dude @ 2016-09-01 15:43 UTC (permalink / raw)


I have a task with entries Start, Stop, Send, Close and an else clause that does some main processing when none of the entries are processed. So the structure is (very simplified):

task body Connection_Handler is
      Done : Boolean := False;
   begin
      accept Start (Socket : Socket_Type) do
        -- do this first 
      end Start;
      loop
         select when not Done =>
            accept Stop do
               Done := True;
            end Stop;
         or when not Done =>
            accept Send (Socket : Socket_Type; Command : Command_Type) do
               -- do something
            end Send;
         or when not Done =>
            accept Close (Socket : Socket_Type) do
               -- do something
               end Close;
         else
            if not Done then
               -- receive data if necessary using GNAT.sockets.Check_Selector
               -- while no data is sent
            end if;
         end select;
         exit when Done;
      end loop;
   end Connection_Handler;

However, when Stop is called and Done set to True, I get 

  raised TASKING_ERROR : s-tasren.adb:445

as an exception in my AUnit test harness and the test ends prematurely with an error code. This occurs in the main program task, or at least if I add a catch-all exception handler in the above task body, it is *not* triggered there.

I thought this occurs perhaps because there is no terminate alternative, but if I add:
 
   or terminate;

before the else part, I get the error message "else part not allowed with other alternatives". So this is not possible.

Is there a way to stop the task gracefully (without abort) but also do some continuous processing like in the else part? Does anybody have an idea what might cause this error?


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

* Re: Rendezvous with select ... else and "or terminate" not possible - but how do I quit this task?
  2016-09-01 15:43 Rendezvous with select ... else and "or terminate" not possible - but how do I quit this task? Some Dude
@ 2016-09-01 16:05 ` J-P. Rosen
  2016-09-01 16:10 ` Dmitry A. Kazakov
  2016-09-01 21:30 ` Some Dude
  2 siblings, 0 replies; 4+ messages in thread
From: J-P. Rosen @ 2016-09-01 16:05 UTC (permalink / raw)


Le 01/09/2016 à 17:43, Some Dude a écrit :

Small remark: you can get rid of "Done":

task body Connection_Handler is
begin
      accept Start (Socket : Socket_Type) do
        -- do this first
      end Start;
      loop
         select
            accept Stop;
            exit;
         or
            accept Send (Socket : Socket_Type; Command : Command_Type) do
               -- do something
            end Send;
         or
            accept Close (Socket : Socket_Type) do
               -- do something
             end Close;
         else
             -- receive data if necessary using GNAT.sockets.Check_Selector
             -- while no data is sent
         end select;
      end loop;
end Connection_Handler;

> However, when Stop is called and Done set to True, I get 
> 
>   raised TASKING_ERROR : s-tasren.adb:445
Presumably, this is due to some other task trying to rendezvous with
Connection_Handler after it has completed.

-- 
J-P. Rosen
Adalog
2 rue du Docteur Lombard, 92441 Issy-les-Moulineaux CEDEX
Tel: +33 1 45 29 21 52, Fax: +33 1 45 29 25 00
http://www.adalog.fr

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

* Re: Rendezvous with select ... else and "or terminate" not possible - but how do I quit this task?
  2016-09-01 15:43 Rendezvous with select ... else and "or terminate" not possible - but how do I quit this task? Some Dude
  2016-09-01 16:05 ` J-P. Rosen
@ 2016-09-01 16:10 ` Dmitry A. Kazakov
  2016-09-01 21:30 ` Some Dude
  2 siblings, 0 replies; 4+ messages in thread
From: Dmitry A. Kazakov @ 2016-09-01 16:10 UTC (permalink / raw)


On 2016-09-01 17:43, Some Dude wrote:
> I have a task with entries Start, Stop, Send, Close and an else
> clause  that does some main processing when none of the entries are processed.
> So the structure is (very simplified):
>
> task body Connection_Handler is
>       Done : Boolean := False;
>    begin
>       accept Start (Socket : Socket_Type) do
>         -- do this first
>       end Start;
>       loop
>          select when not Done =>
>             accept Stop do
>                Done := True;
>             end Stop;
>          or when not Done =>
>             accept Send (Socket : Socket_Type; Command : Command_Type) do
>                -- do something
>             end Send;
>          or when not Done =>
>             accept Close (Socket : Socket_Type) do
>                -- do something
>                end Close;
>          else
>             if not Done then
>                -- receive data if necessary using GNAT.sockets.Check_Selector
>                -- while no data is sent
>             end if;
>          end select;
>          exit when Done;
>       end loop;
>    end Connection_Handler;
>
> However, when Stop is called and Done set to True, I get
>
>   raised TASKING_ERROR : s-tasren.adb:445

Because the task is terminated Done = True, obviously.

The design is flawed. You cannot accept anything when sitting in 
Check_Selector.

An alternative design is (very simplified):

    loop
       -- fill socket sets, checking selector ruins them
       Check_Selector (...); -- with some reasonable timeout
       case Status is
          when Completed =>
             -- Service read/write sockets
          when Aborted | Timeout =>
             -- service task messages queue
          ...
       end case;
    end loop;

No rendezvous, you push a message into a queue and then abort selector 
which falls into Status Aborted which gives the task an opportunity to 
inspect the queue.

Then you need not Send entry/message. Sending is driven by write socket 
events. So when the socket is ready to be written Status = Completed and 
the socket is in the write set, you send another portion of data from 
the output ring buffer. Note that you need the buffer in any case 
because you don't know how much the socket is ready to accept.

You don't interrupt the task for writing the buffer. It can be done 
asynchronously.

P.S. You can find an example of working design in Simple Components:

http://www.dmitry-kazakov.de/ada/components.htm#multiple_GNAT.Sockets.Servers

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

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

* Re: Rendezvous with select ... else and "or terminate" not possible - but how do I quit this task?
  2016-09-01 15:43 Rendezvous with select ... else and "or terminate" not possible - but how do I quit this task? Some Dude
  2016-09-01 16:05 ` J-P. Rosen
  2016-09-01 16:10 ` Dmitry A. Kazakov
@ 2016-09-01 21:30 ` Some Dude
  2 siblings, 0 replies; 4+ messages in thread
From: Some Dude @ 2016-09-01 21:30 UTC (permalink / raw)


I've found a solution similar to Dmitry's suggestion by using a protected object. The error no longer occurs and it's even faster.

Thanks a lot! 

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

end of thread, other threads:[~2016-09-01 21:30 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-09-01 15:43 Rendezvous with select ... else and "or terminate" not possible - but how do I quit this task? Some Dude
2016-09-01 16:05 ` J-P. Rosen
2016-09-01 16:10 ` Dmitry A. Kazakov
2016-09-01 21:30 ` Some Dude

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