comp.lang.ada
 help / color / mirror / Atom feed
From: "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de>
Subject: Re: Rendezvous with select ... else and "or terminate" not possible - but how do I quit this task?
Date: Thu, 1 Sep 2016 18:10:51 +0200
Date: 2016-09-01T18:10:51+02:00	[thread overview]
Message-ID: <nq9juj$9uu$1@gioia.aioe.org> (raw)
In-Reply-To: 6e4d6fc1-dcb9-454a-8c1e-df090224438e@googlegroups.com

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

  parent reply	other threads:[~2016-09-01 16:10 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
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 [this message]
2016-09-01 21:30 ` Some Dude
replies disabled

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