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
next prev 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