comp.lang.ada
 help / color / mirror / Atom feed
* tasksing and TCP sockets
@ 2006-01-30 22:12 Rolf
  2006-01-31  2:40 ` Stephen Leake
                   ` (2 more replies)
  0 siblings, 3 replies; 17+ messages in thread
From: Rolf @ 2006-01-30 22:12 UTC (permalink / raw)


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




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

* Re: tasksing and TCP sockets
  2006-01-30 22:12 tasksing and TCP sockets Rolf
@ 2006-01-31  2:40 ` Stephen Leake
  2006-01-31  6:59   ` tmoran
  2006-01-31 22:52   ` Rolf
  2006-01-31  3:02 ` Steve
  2006-01-31 10:09 ` Dmitry A. Kazakov
  2 siblings, 2 replies; 17+ messages in thread
From: Stephen Leake @ 2006-01-31  2:40 UTC (permalink / raw)


"Rolf" <rolf.ebert_nospam_@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



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

* Re: tasksing and TCP sockets
  2006-01-30 22:12 tasksing and TCP sockets Rolf
  2006-01-31  2:40 ` Stephen Leake
@ 2006-01-31  3:02 ` Steve
  2006-01-31 10:09 ` Dmitry A. Kazakov
  2 siblings, 0 replies; 17+ messages in thread
From: Steve @ 2006-01-31  3:02 UTC (permalink / raw)


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 2195 bytes --]

"Rolf" <rolf.ebert_nospam_@gmx.net> wrote in message 
news:1138659171.491931.322480@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)





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

* Re: tasksing and TCP sockets
  2006-01-31  2:40 ` Stephen Leake
@ 2006-01-31  6:59   ` tmoran
  2006-01-31 23:03     ` Rolf
  2006-02-06  5:02     ` Dave Thompson
  2006-01-31 22:52   ` Rolf
  1 sibling, 2 replies; 17+ messages in thread
From: tmoran @ 2006-01-31  6:59 UTC (permalink / raw)


>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?



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

* Re: tasksing and TCP sockets
  2006-01-30 22:12 tasksing and TCP sockets Rolf
  2006-01-31  2:40 ` Stephen Leake
  2006-01-31  3:02 ` Steve
@ 2006-01-31 10:09 ` Dmitry A. Kazakov
  2006-01-31 21:55   ` Simon Wright
  2 siblings, 1 reply; 17+ messages in thread
From: Dmitry A. Kazakov @ 2006-01-31 10:09 UTC (permalink / raw)


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



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

* Re: tasksing and TCP sockets
  2006-01-31 10:09 ` Dmitry A. Kazakov
@ 2006-01-31 21:55   ` Simon Wright
  2006-02-01  8:54     ` Dmitry A. Kazakov
  0 siblings, 1 reply; 17+ messages in thread
From: Simon Wright @ 2006-01-31 21:55 UTC (permalink / raw)


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

> On 30 Jan 2006 14:12:51 -0800, Rolf wrote:

>>  - 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.

_Something_ has to wait for a socket read! If you're writing your own
'middleware' (lower layers, anyway) that will be you.

Windows is not wonderful for this sort of thing but I have not seen
problems of the sort you describe with a task blocked on the read
(input_t'Input) and other code (either another single task, or some
sort of mutex) for output_t'Output.

>>  - 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.

Probably best to avoid these (I guess that UPD was a typo for UDP) at
the start, but sometimes they are the appropriate solution. Not often,
maybe.



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

* Re: tasksing and TCP sockets
  2006-01-31  2:40 ` Stephen Leake
  2006-01-31  6:59   ` tmoran
@ 2006-01-31 22:52   ` Rolf
  2006-02-01  1:23     ` Stephen Leake
  1 sibling, 1 reply; 17+ messages in thread
From: Rolf @ 2006-01-31 22:52 UTC (permalink / raw)


Stephen Leake wrote:
> "Rolf" <rolf.ebert_nospam_@gmx.net> writes:
>
> > 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,

Does that mean e.g. to set the main task to 10 and the second task to
5?

> 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.

How would I do that? I have no explicit busy wait, I use

  Var := Sensor_Cmd_T'Input (Channel);

If possible, I'd like to keep that easy way of data input and avoid
explicit conversion and read commands.

> > 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.

This is a hobby project.

> > Java for the world simulation.
>
> Yuck. I assume that's not by choice?

The world simulation already exists.  I won't recode it in Ada.  (and I
kind of like Java, too)

> > The simulator sends about 20 packages à 11bytes every 100ms. The
> > application sends typically 2-3 packages per second.
>
> That's certainly "reasonable rates"
>

That is almost nothing!

> > 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.

How?

> 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.
>

I shall check 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.

There is no real Ada compiler on Cygwin.  I use the Windows
(mingw-based) gcc-3.4.4. I shall see if GNAT GPL 2005 gives different
results.

> > - 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.

I suppose it waits in the Sensor_Cmd_T'Input (Channel) routine, but I
am not sure.

> > - what other hints can you give me?
>
> Get an AdaCore support contract.
> 
In a professional environment certainly, but not here ...

    Rolf




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

* Re: tasksing and TCP sockets
  2006-01-31  6:59   ` tmoran
@ 2006-01-31 23:03     ` Rolf
  2006-02-01  1:26       ` Stephen Leake
  2006-02-06  5:02     ` Dave Thompson
  1 sibling, 1 reply; 17+ messages in thread
From: Rolf @ 2006-01-31 23:03 UTC (permalink / raw)



tmoran@acm.org wrote:
>   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?

The real sensor hardware will be directly connected to the I/O pins of
the mcu.  I think that counts as polling.  The application code simply
reads variables from the h/w abstraction layer.




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

* Re: tasksing and TCP sockets
  2006-01-31 22:52   ` Rolf
@ 2006-02-01  1:23     ` Stephen Leake
  2006-02-01 21:12       ` Simon Wright
  0 siblings, 1 reply; 17+ messages in thread
From: Stephen Leake @ 2006-02-01  1:23 UTC (permalink / raw)


"Rolf" <rolf.ebert_nospam_@gmx.net> writes:

> Stephen Leake wrote:
>> "Rolf" <rolf.ebert_nospam_@gmx.net> writes:
>>
>> > 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,
>
> Does that mean e.g. to set the main task to 10 and the second task to
> 5?

Well, I don't know, since I don't know the details of your project.
But it is likely that one should have a higher priority than the
other. The default is for all tasks to have the same priority.

>> 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.
>
> How would I do that? I have no explicit busy wait, I use
>
>   Var := Sensor_Cmd_T'Input (Channel);
>
> If possible, I'd like to keep that easy way of data input and avoid
> explicit conversion and read commands.

Hmm. I don't know how this maps to Read_Socket commands. I would guess
that it waits for the number of Stream_Elements in Sensor_Cmd_T to be
available. But it might wait longer than that, especially if
Sensor_Cmd_T is unconstrained.

You could do a Read_Socket into a Stream_Array, and then do 'Input
from that. That would make it clearer when the task is suspended.

>> > 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.
>
> This is a hobby project.

Ok.

>> > - 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.
>
> I suppose it waits in the Sensor_Cmd_T'Input (Channel) routine, but I
> am not sure.

There is an option that expands tasking constructs into lower-level
Ada code, and outputs the source. That may help here, to show what is
going on.

-- 
-- Stephe



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

* Re: tasksing and TCP sockets
  2006-01-31 23:03     ` Rolf
@ 2006-02-01  1:26       ` Stephen Leake
  2006-02-01  7:39         ` Rolf
  0 siblings, 1 reply; 17+ messages in thread
From: Stephen Leake @ 2006-02-01  1:26 UTC (permalink / raw)


"Rolf" <rolf.ebert_nospam_@gmx.net> writes:

> tmoran@acm.org wrote:
>>   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?
>
> The real sensor hardware will be directly connected to the I/O pins of
> the mcu.  I think that counts as polling.  The application code simply
> reads variables from the h/w abstraction layer.

How do those "variables" get set? 

Does one of the IO pins generate an interrupt, that triggers the h/w
abstraction layer "read all pins" function?

Or is the h/w abstraction layer a cyclic executor, driven by a clock?

How does the application know when to read the variables? By a clock,
or some interrupt/event from the h/w abstraction layer?

-- 
-- Stephe



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

* Re: tasksing and TCP sockets
  2006-02-01  1:26       ` Stephen Leake
@ 2006-02-01  7:39         ` Rolf
  2006-02-01 14:52           ` Stephen Leake
  0 siblings, 1 reply; 17+ messages in thread
From: Rolf @ 2006-02-01  7:39 UTC (permalink / raw)


Stephen Leake wrote:
> "Rolf" <rolf.ebert_nospam_@gmx.net> writes:
>
> > tmoran@acm.org wrote:
> >>   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?
> >
> > The real sensor hardware will be directly connected to the I/O pins of
> > the mcu.  I think that counts as polling.  The application code simply
> > reads variables from the h/w abstraction layer.
>
> How do those "variables" get set?
>
> Does one of the IO pins generate an interrupt, that triggers the h/w
> abstraction layer "read all pins" function?
>
> Or is the h/w abstraction layer a cyclic executor, driven by a clock?
>
> How does the application know when to read the variables? By a clock,
> or some interrupt/event from the h/w abstraction layer?

The main program essentially looks like this:

loop
   Read_Sens;

   Behave;

   delay until Next;
   Next := Next + Period; -- Period == 0.1 sec typ.
end loop;

The call to Read_Sens is commented out in the simulation case and
replaced by the second thread as outlined in the original posting. The
sensor data are global variables in a package spec. The Behave reads
them whenever it thinks it needs their values.

The world simulation program at the other end of the TCP socket does
not know about the internal timing of the application (perhaps I should
add a synchronization protocol, now that I think of it)




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

* Re: tasksing and TCP sockets
  2006-01-31 21:55   ` Simon Wright
@ 2006-02-01  8:54     ` Dmitry A. Kazakov
  0 siblings, 0 replies; 17+ messages in thread
From: Dmitry A. Kazakov @ 2006-02-01  8:54 UTC (permalink / raw)


On Tue, 31 Jan 2006 21:55:57 +0000, Simon Wright wrote:

> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:
> 
>> On 30 Jan 2006 14:12:51 -0800, Rolf wrote:
> 
>>>  - 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.
> 
> _Something_ has to wait for a socket read! If you're writing your own
> 'middleware' (lower layers, anyway) that will be you.

It depends. The point is, that it should not the application task.
Especially because socket I/O events are not directly mapped into
application events, due to buffering. So if the application needs fresh
data it can wait for a protected object, which state is changed by the
reader task (the reader waits, of course.) However more often, when dealing
with sensors and actors (which are continuous-state things), the
application does not wait at all, but just takes the last available value.
[ Quality of service checks, and generating consequent alarms is a
middleware's responsibility. ]

>>>  - 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.
> 
> Probably best to avoid these (I guess that UPD was a typo for UDP) at
> the start, but sometimes they are the appropriate solution. Not often,
> maybe.

Yes.

Maybe off-topic, but. Multicasting finally came. Now there are viable
alternatives to UDP. For example, PGM is a reliable multicasting protocol.

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



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

* Re: tasksing and TCP sockets
  2006-02-01  7:39         ` Rolf
@ 2006-02-01 14:52           ` Stephen Leake
  2006-02-03 20:33             ` Rolf
  0 siblings, 1 reply; 17+ messages in thread
From: Stephen Leake @ 2006-02-01 14:52 UTC (permalink / raw)


"Rolf" <rolf.ebert_nospam_@gmx.net> writes:

> Stephen Leake wrote:
>> "Rolf" <rolf.ebert_nospam_@gmx.net> writes:
>>
>> > tmoran@acm.org wrote:
>> >>   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?
>> >
>> > The real sensor hardware will be directly connected to the I/O pins of
>> > the mcu.  I think that counts as polling.  The application code simply
>> > reads variables from the h/w abstraction layer.
>>
>> How do those "variables" get set?
>>
>> Does one of the IO pins generate an interrupt, that triggers the h/w
>> abstraction layer "read all pins" function?
>>
>> Or is the h/w abstraction layer a cyclic executor, driven by a clock?
>>
>> How does the application know when to read the variables? By a clock,
>> or some interrupt/event from the h/w abstraction layer?
>
> The main program essentially looks like this:
>
> loop
>    Read_Sens;
>
>    Behave;
>
>    delay until Next;
>    Next := Next + Period; -- Period == 0.1 sec typ.
> end loop;

Ok. So Read_Sens runs the h/w abstraction layer, Behave is the
application layer.

> The call to Read_Sens is commented out in the simulation case and
> replaced by the second thread as outlined in the original posting. 

Better to not edit the code, but define an alternate body for
Read_Sens. Not a big deal.

> The sensor data are global variables in a package spec. The Behave
> reads them whenever it thinks it needs their values.

Ok.

> The world simulation program at the other end of the TCP socket does
> not know about the internal timing of the application (perhaps I should
> add a synchronization protocol, now that I think of it)

I'm still not clear where the sockets are. I think Read_Sens reads
from a socket to get the simulated sensor values. Does it try to read
data for all variables from the socket _every_ time it is called? Or
does it check to see if some new data is available?

Behave writes to a socket for user display?

Then the question is what drives the simulation; does it wait for
Read_Sens to read data, or just run at some rate? Does the simulation
react to anything Behave does?

Yes, you need synchronization between the simulation and Read_Sens,
and possibly Behave. That is probably the root cause of your problem.

-- 
-- Stephe



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

* Re: tasksing and TCP sockets
  2006-02-01  1:23     ` Stephen Leake
@ 2006-02-01 21:12       ` Simon Wright
  0 siblings, 0 replies; 17+ messages in thread
From: Simon Wright @ 2006-02-01 21:12 UTC (permalink / raw)


Stephen Leake <stephen_leake@acm.org> writes:

> Hmm. I don't know how this maps to Read_Socket commands. I would guess
> that it waits for the number of Stream_Elements in Sensor_Cmd_T to be
> available. But it might wait longer than that, especially if
> Sensor_Cmd_T is unconstrained.

If the type is unconstrained, 'Input will read dope info (whose length
it does know) and then read the number of bytes specified by the dope
info. It uses recv() for TCP, recvfrom() for UDP (well, this is 4.0.0
on Darwin, but as I recall this part is pretty standard).

> You could do a Read_Socket into a Stream_Array, and then do 'Input
> from that. That would make it clearer when the task is suspended.

That doesn't work (for TCP) unless you know how large the object is on
the wire!

On the other hand for UDP messages, you *must* read the whole packet
into a stream array (at least as large as the largest supported
packet) and do 'Input from that, because you really really want to
make only one call to the OS socket interface. Similarly for 'Output.



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

* Re: tasksing and TCP sockets
  2006-02-01 14:52           ` Stephen Leake
@ 2006-02-03 20:33             ` Rolf
  2006-02-04 12:48               ` Stephen Leake
  0 siblings, 1 reply; 17+ messages in thread
From: Rolf @ 2006-02-03 20:33 UTC (permalink / raw)


Stephen Leake wrote:
> "Rolf" <rolf.ebert_nospam_@gmx.net> writes:
>
> > The main program essentially looks like this:
> >
> > loop
> >    Read_Sens;
> >
> >    Behave;
> >
> >    delay until Next;
> >    Next := Next + Period; -- Period == 0.1 sec typ.
> > end loop;
>
> Ok. So Read_Sens runs the h/w abstraction layer, Behave is the
> application layer.

More or less. Behave also calls a write routine in the abstraction
layer.

> > The world simulation program at the other end of the TCP socket does
> > not know about the internal timing of the application (perhaps I should
> > add a synchronization protocol, now that I think of it)
>
> I'm still not clear where the sockets are. I think Read_Sens reads
> from a socket to get the simulated sensor values. Does it try to read
> data for all variables from the socket _every_ time it is called? Or
> does it check to see if some new data is available?

Read_Sens reads the hardware sensors in the non-simulated case and
writes them to global variables. It reads them from a protected object
when communicating via TCP. The second task (besides the main program)
continuously reads from the socket and writes to the protected object.
That second task and the protected object do not exist in the
non-simulated case.

> Behave writes to a socket for user display?

and it changes the world in the world simulation. The world simulation
also has a GUI.

> Then the question is what drives the simulation; does it wait for
> Read_Sens to read data, or just run at some rate? Does the simulation
> react to anything Behave does?
>
> Yes, you need synchronization between the simulation and Read_Sens,
> and possibly Behave. That is probably the root cause of your problem.

that is certainly true and I have to think about it again.

No, the root cause of my problem was a buggy socket implementation in
gcc-3.4.4 (at least I think so). I recompiled my program with GNAT GPL
2005 and it worked without any other modification




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

* Re: tasksing and TCP sockets
  2006-02-03 20:33             ` Rolf
@ 2006-02-04 12:48               ` Stephen Leake
  0 siblings, 0 replies; 17+ messages in thread
From: Stephen Leake @ 2006-02-04 12:48 UTC (permalink / raw)


"Rolf" <rolf.ebert_nospam_@gmx.net> writes:

> Stephen Leake wrote:
>> "Rolf" <rolf.ebert_nospam_@gmx.net> writes:
>>
>> > The main program essentially looks like this:
>> >
>> > loop
>> >    Read_Sens;
>> >
>> >    Behave;
>> >
>> >    delay until Next;
>> >    Next := Next + Period; -- Period == 0.1 sec typ.
>> > end loop;
>>
>> Ok. So Read_Sens runs the h/w abstraction layer, Behave is the
>> application layer.
>
> More or less. Behave also calls a write routine in the abstraction
> layer.

Ah. That's how it "changes the world". Ok.

>> > The world simulation program at the other end of the TCP socket does
>> > not know about the internal timing of the application (perhaps I should
>> > add a synchronization protocol, now that I think of it)
>>
>> I'm still not clear where the sockets are. I think Read_Sens reads
>> from a socket to get the simulated sensor values. Does it try to read
>> data for all variables from the socket _every_ time it is called? Or
>> does it check to see if some new data is available?
>
> Read_Sens reads the hardware sensors in the non-simulated case and
> writes them to global variables. It reads them from a protected object
> when communicating via TCP. The second task (besides the main program)
> continuously reads from the socket and writes to the protected object.

"continously" is a dangerous term; that's 100% CPU? I assume this is
where the "delay" comes in, and this is actually "periodically".

> That second task and the protected object do not exist in the
> non-simulated case.
>
>> Behave writes to a socket for user display?
>
> and it changes the world in the world simulation. The world simulation
> also has a GUI.

Ok.

>> Then the question is what drives the simulation; does it wait for
>> Read_Sens to read data, or just run at some rate? Does the simulation
>> react to anything Behave does?
>>
>> Yes, you need synchronization between the simulation and Read_Sens,
>> and possibly Behave. That is probably the root cause of your problem.
>
> that is certainly true and I have to think about it again.
>
> No, the root cause of my problem was a buggy socket implementation in
> gcc-3.4.4 (at least I think so). I recompiled my program with GNAT GPL
> 2005 and it worked without any other modification

Ah. Good that it works now.

-- 
-- Stephe



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

* Re: tasksing and TCP sockets
  2006-01-31  6:59   ` tmoran
  2006-01-31 23:03     ` Rolf
@ 2006-02-06  5:02     ` Dave Thompson
  1 sibling, 0 replies; 17+ messages in thread
From: Dave Thompson @ 2006-02-06  5:02 UTC (permalink / raw)


On Tue, 31 Jan 2006 00:59:45 -0600, tmoran@acm.org wrote:

> >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".

In Windows-the-GUI, or at least for a GUI task/thread on Windows.

But for Windows-the-OS (a non-GUI task/thread or "console" program)
plain old recv() and if you wish select() work just fine.

<snip>

<OFFTOPIC> I feel impelled to re-quote this prior line:

>   TCP server that simulates the world

I realize it makes sense in the context of the OP system description,
but just looking at it in isolation reminded me all too forcefully of
any number of past project breakdown/deliverable items with
demure-looking descriptions that turned out to be disasters. <G?> </>

- David.Thompson1 at worldnet.att.net



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

end of thread, other threads:[~2006-02-06  5:02 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2006-01-30 22:12 tasksing and TCP sockets Rolf
2006-01-31  2:40 ` Stephen Leake
2006-01-31  6:59   ` tmoran
2006-01-31 23:03     ` Rolf
2006-02-01  1:26       ` Stephen Leake
2006-02-01  7:39         ` Rolf
2006-02-01 14:52           ` Stephen Leake
2006-02-03 20:33             ` Rolf
2006-02-04 12:48               ` Stephen Leake
2006-02-06  5:02     ` Dave Thompson
2006-01-31 22:52   ` Rolf
2006-02-01  1:23     ` Stephen Leake
2006-02-01 21:12       ` Simon Wright
2006-01-31  3:02 ` Steve
2006-01-31 10:09 ` Dmitry A. Kazakov
2006-01-31 21:55   ` Simon Wright
2006-02-01  8:54     ` Dmitry A. Kazakov

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