From: Rolf on
Consider an application that communicates with its environment via
sensors and actors. For testing purposes the low level access to the
sensor and actor data gets replaced by a TCP socket communication whose
other end simulates the world, i.e. the world simulation continuously
writes sensor data to the socket and accepts commands as actor data.

+-----------------------+
| |
| application |
| |
+-----------------------+
| h/w abstraction |
| sensors | actors |
+-----------------------+
|
TCP client
|
|
|
TCP server that simulates the world


In a stripped down version I can succesfully connect to the server
(using GNAT.Sockets) and either read the sensor data *or* write actor
data. The program is currently split in two tasks. One tasks contains
the application code and the actor communication (using
type_id'output(channel)). The second tasks gets started during program
initialisation. It reads the data from the socket via
type_id'input(channel) and provides the data to the application through
a protected object.

The problem that I face is that the second task seems to starve the
first one. As soon as it is active, the application does not generate
debug output anymore.

Some background info: gcc-3.4.4 on Windows XP. Java for the world
simulation. The simulator sends about 20 packages à 11bytes every
100ms. The application sends typically 2-3 packages per second. I have
delay statements in both main loops (varied between 0.0 and 0.2
seconds).

My questions:
- is that a reasonable tasking approach?
- I don't know much about sockets (or better I don't remember much).
Does a waiting read (in the second task) block a write in the first
task?
- how can I interrupt the waiting read task to force activity in the
main task?
- what other hints can you give me?


TIA
Rolf

From: Stephen Leake on
"Rolf" <rolf.ebert_nospam_(a)gmx.net> writes:

> Consider an application that communicates with its environment via
> sensors and actors. For testing purposes the low level access to the
> sensor and actor data gets replaced by a TCP socket communication whose
> other end simulates the world, i.e. the world simulation continuously
> writes sensor data to the socket and accepts commands as actor data.
>
> +-----------------------+
> | |
> | application |
> | |
> +-----------------------+
> | h/w abstraction |
> | sensors | actors |
> +-----------------------+
> |
> TCP client
> |
> |
> |
> TCP server that simulates the world
>

Ok, this makes sense.

> In a stripped down version I can succesfully connect to the server
> (using GNAT.Sockets) and either read the sensor data *or* write actor
> data. The program is currently split in two tasks. One tasks contains
> the application code and the actor communication (using
> type_id'output(channel)). The second tasks gets started during program
> initialisation. It reads the data from the socket via
> type_id'input(channel) and provides the data to the application through
> a protected object.
>
> The problem that I face is that the second task seems to starve the
> first one. As soon as it is active, the application does not generate
> debug output anymore.

You need to set the priorities correctly, and you need to ensure that
there are no busy waits; the second task should be _suspended_ waiting
on socket completions, not polling for them. And the simulator must
send data at a reasonable rate, not too fast.

> Some background info: gcc-3.4.4 on Windows XP.

That may be a problem. I find the commercially supported GNAT to be
less broken.

> Java for the world simulation.

Yuck. I assume that's not by choice?

> The simulator sends about 20 packages ? 11bytes every 100ms. The
> application sends typically 2-3 packages per second.

That's certainly "reasonable rates"

> I have delay statements in both main loops (varied between 0.0 and
> 0.2 seconds).

You should _not_ need delay statements. Redesign to be waiting on
socket completions.

Or, if you are designing to a cyclic execution, you can poll on the
sockets, but just once per cycle. You can use
GNAT.Sockets.Control_Socket for that.

> My questions:
> - is that a reasonable tasking approach?

In general, yes. But the details matter a lot.

> - I don't know much about sockets (or better I don't remember
> much). Does a waiting read (in the second task) block a write in the
> first task?

Not in Windows with GNAT 5.03a. gcc-3.4.4 on Cygwin may be different.

> - how can I interrupt the waiting read task to force activity in the
> main task?

Depends on how it is waiting. If is in a GNAT.Sockets.Receive_Socket,
you can't (short of shutting down the socket). So periodic polling
might be better.

> - what other hints can you give me?

Get an AdaCore support contract.

--
-- Stephe
From: Steve on
"Rolf" <rolf.ebert_nospam_(a)gmx.net> wrote in message
news:1138659171.491931.322480(a)g49g2000cwa.googlegroups.com...
[snip]
>In a stripped down version I can succesfully connect to the server
>(using GNAT.Sockets) and either read the sensor data *or* write actor
>data. The program is currently split in two tasks. One tasks contains
>the application code and the actor communication (using
>type_id'output(channel)). The second tasks gets started during program
>initialisation. It reads the data from the socket via
>type_id'input(channel) and provides the data to the application through
>a protected object.
>
>The problem that I face is that the second task seems to starve the
>first one. As soon as it is active, the application does not generate
>debug output anymore.
>
>Some background info: gcc-3.4.4 on Windows XP. Java for the world
>simulation. The simulator sends about 20 packages ? 11bytes every
>100ms. The application sends typically 2-3 packages per second. I have
>delay statements in both main loops (varied between 0.0 and 0.2
>seconds).
>
>My questions:
> - is that a reasonable tasking approach?
> - I don't know much about sockets (or better I don't remember much).
>Does a waiting read (in the second task) block a write in the first
>task?
> - how can I interrupt the waiting read task to force activity in the
>main task?
> - what other hints can you give me?
>
>
>TIA
> Rolf

Your approach sounds reasonable to me.
I wrote my own wrappers for Win32 sockets API before GNAT.Sockets
was born, so I can't say much about their behavior... but, using the
Win32 API, I have been able to have one task reading a socket and another
task writing the same socket using blocking TCP/IP sockets with no
issues of reads causing writes to block or vise-versa.

I have seen the type of problem you describe with serial I/O on windows.
With serial I/O you have to open the device file with an OVERLAPPED
attirbute or one task pending on a read will cause a write to block As I
mentioned earlier, I'm not familiar with the GNAT.Sockets implementation
so it is entirely possible that you are seeing the same behavior because of
the socket implementation.

Steve
(The Duck)


From: tmoran on
>You should _not_ need delay statements. Redesign to be waiting on
>socket completions.
If the allowed response latency isn't terribly short (and it doesn't
sound like it is here) there's nothing wrong with letting the system
buffer up input while the reading task does a delay. Just use a blocking
socket and poll to see if there's more input data available. Remember
that "waiting on socket completions" in Windows means "polling the Windows
message loop for a socket completion message".
But it seems to me that if the object is to use TCP to emulate hardware,
one should design for that hardware and do whatever is needed with UDP or
TCP to make the best emulation. Is the intended hardware going to be
polled or generate interrupts or Windows messages or what?
From: Dmitry A. Kazakov on
On 30 Jan 2006 14:12:51 -0800, Rolf wrote:

> Consider an application that communicates with its environment via
> sensors and actors. For testing purposes the low level access to the
> sensor and actor data gets replaced by a TCP socket communication whose
> other end simulates the world, i.e. the world simulation continuously
> writes sensor data to the socket and accepts commands as actor data.
>
> +-----------------------+
> | |
> | application |
> | |
> +-----------------------+
> | h/w abstraction |
> | sensors | actors |
> +-----------------------+
> |
> TCP client
> |
> |
> |
> TCP server that simulates the world

This architecture is called "middleware." In a more elaborated form it
looks like:

Application1 ... ApplicationN
| (application API)
Middleware [state variables to access]
| (driver API)
Hardware abstraction layer [middleware-"drivers"]
| |
Network protocol |
| |
TCP/IP based layer Hardware registers
| |
Ethernet A/D converter

BTW, in general it is not a 2-tier architecture, so client-server approach
might appear difficult.

> In a stripped down version I can succesfully connect to the server
> (using GNAT.Sockets) and either read the sensor data *or* write actor
> data.

Middleware usually provides a bit more. You will also need some
synchronization mechanisms [any hardware has limited speed], different
publishing/subscribing policies for periodic and event-controlled data etc.

> The program is currently split in two tasks. One tasks contains
> the application code and the actor communication (using
> type_id'output(channel)). The second tasks gets started during program
> initialisation. It reads the data from the socket via
> type_id'input(channel) and provides the data to the application through
> a protected object.

It is a design problem. I would factor out the middleware kernel first.
Note that there is no logical difference between Ethernet TCP/IP and A/D
converter. Both are devices for the middleware. The very purpose of
middleware is to hide any difference from the application.

> My questions:
> - is that a reasonable tasking approach?

You might need one task per device to decouple application from the
middleware. When an I/O is started on a middleware variable, the
application task just continues to the time point where it says: now I need
the result.

> - I don't know much about sockets (or better I don't remember much).
> Does a waiting read (in the second task) block a write in the first
> task?

Usually not. Note that you must wait not for a socket read, but for a
"variable-update" event from the middleware layer.

> - how can I interrupt the waiting read task to force activity in the
> main task?

Don't. A waiting task does not consume CPU time, so why would you like to
interrupt it?

> - what other hints can you give me?

Never ever use UPD, avoid TCP_NO_DELAY with TCP/IP. The first is unreliable
for your purpose, the second quickly brings the network down. Carefully
design your network protocol, most probably it will be full-duplex in the
end. Make it platform independent from the start (htonl issues etc.)
Consider connection start/down/repair issues with a great care, it will pay
off later. Then, well, real-time issues. Under Windows the above can
perform with 5-10ms [this is the figures of our commercial middleware.] If
you want it faster, you have a problem then. Windows is not very suitable
for this. You might also have to consider numerous industrial Ethernet
semi-standards and time-triggered protocols instead of standard Ethernet.

Good luck!

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