Architecture design

A

Alessio Sangalli

Hi all. I am writing the documentation for the program I'm going to
develop (yes, documentation before the implementation, it's awesome!).

In short, it will run on an embedded platform wint Linux as OS. I have
some hardware devices that have to send data to and receive data from a
server on the network. I will use one TCP stream for all the communication.

Basically what I plan to do is the following:
- for the program to be as modular as possible, it will look in a
directory for "plugins" implemented with shared objects. Every plugin
will declare what "type" or data it will send or receive.
- A "main" thread will start each "plugin" as a separate thread.
- Every "plugin-thread" will manage the hardware; it will eventually
have something to send to the server and viceversa

What is the best way to implement this data exchange? I'd prefer not to
execute code found in the plugin from the "main-thread" because a poorly
written plugin may block for too much time (or indefinitely) the
operations of the rest of the plugins and the data transfer.

An idea I had was to have the main-thread or the plugin-threads insert
data in a thread-safe queue, and then send a signal to the recipient
(main or plugin depending on the data flow) to inform it has to process
the data.

What do you think?
Alessio
 
B

Ben Bacarisse

Alessio Sangalli said:
In short, it will run on an embedded platform wint Linux as OS.

comp.unix.programmer is probably a reasonable place to get the overall
design discussed.

An idea I had was to have the main-thread or the plugin-threads insert
data in a thread-safe queue, and then send a signal to the recipient
(main or plugin depending on the data flow) to inform it has to process
the data.

....and if you can't be talked out of using threads,
comp.programming.threads has some very good people on it who can help
with any of these specifics.
 
A

Alessio Sangalli

Ben said:
comp.unix.programmer is probably a reasonable place to get the overall
design discussed.

Thanks for the direction

...and if you can't be talked out of using threads,

Why does everybody hates threads so much :) I often fail to see the
advantages of processes for 'small' things.

bye
Alessio
 
L

Lew Pitcher

Ben Bacarisse wrote: [snip]
...and if you can't be talked out of using threads,

Why does everybody hates threads so much :) I often fail to see the
advantages of processes for 'small' things.

<off-topic>
My guess is that threads are often more bother than they are worth.

Given the possibility of programmed creation of processes (i.e. an api to
launch processes), threads are redundant.

In many environments, threads do not provide any execution-speed advantage
over processes (the usual "big" argument for threads is that "the
context-switch overhead for a thread is 'less' than the context-switch
overhead for a process", but in many systems, threads and processes have
the same context-switch overhead).

Threads usually require a greater level of programming support than
processes.

Programs that use threads often suffer from poor design/implementation,
causing any advantage that threads offer to be lost (I'm thinking of
deadlock and race conditions, and of failure to disentangle logic).

There are as effective ways of data sharing for processes as there are for
threads, and inter-process data sharing usually enforces a level of data
protection that inter-thread data sharing avoids.

HTH
</off-topic>

--
Lew Pitcher

Master Codewright & JOAT-in-training | Registered Linux User #112576
http://pitcher.digitalfreehold.ca/ | GPG public key available by request
---------- Slackware - Because I know what I'm doing. ------
 
S

s0suk3

Ben Bacarisse wrote: [snip]
...and if you can't be talked out of using threads,
Why does everybody hates threads so much :) I often fail to see the
advantages of processes for 'small' things.

<off-topic>
My guess is that threads are often more bother than they are worth.

Given the possibility of programmed creation of processes (i.e. an api to
launch processes), threads are redundant.

fork() is known to be the process creation equivalent to threads
creation, and it provides most of the flexibility that threading does.
However, fork() is less efficient that threads, and much less portable
than threads (since it's only supported on POSIX systems), so even
when fork() is available, threads are not redundant. When fork() is
not available, you can only rely on creation of external processes,
which are much less flexible (e.g., there are less mechanisms for IPC)
and less efficient than threads.
Threads usually require a greater level of programming support than
processes.

Maybe, but in a well-designed application (as opposed to in a quick-
and-dirty script), that's the least of the things to worry about. You
just apply an optimal level of abstraction. Furthermore, "greater
level of programming support" often means more functionality, which
results in an increase of simplicity and flexibility in some
application areas such as IPC modeling.
Programs that use threads often suffer from poor design/implementation,

That has nothing to do with threads themselves. Maybe you've seen a
lot of such applications, but they're poor design is purely their
implementors' fault.
causing any advantage that threads offer to be lost (I'm thinking of
deadlock and race conditions, and of failure to disentangle logic).

There are as effective ways of data sharing for processes as there are for
threads,

When you use fork(), you do have some, but not as many as with
threads. For example, how about a synchronized, shared, global,
producer/consumer queue of data?
and inter-process data sharing usually enforces a level of data
protection that inter-thread data sharing avoids.

Sebastian
 
K

Keith Thompson

fork() is known to be the process creation equivalent to threads
creation, and it provides most of the flexibility that threading does.
However, fork() is less efficient that threads, and much less portable
than threads (since it's only supported on POSIX systems), so even
when fork() is available, threads are not redundant.
[...]

fork() is less portable than threads? Huh?
 
S

s0suk3

(e-mail address removed) writes:

[...]> fork() is known to be the process creation equivalent to threads
creation, and it provides most of the flexibility that threading does.
However, fork() is less efficient that threads, and much less portable
than threads (since it's only supported on POSIX systems), so even
when fork() is available, threads are not redundant.

[...]

fork() is less portable than threads?  Huh?

What do you mean?

Well, strictly speaking, in C, threads are as portable as fork()
(i.e., non-portable), since they're not supported by ISO and you'll
need to rely on system-specific functionality in order to use either
one of them. As far as for POSIX, they're also equivalently portable:
any POSIX system supports both fork() and pthreads.

But what I mean is that threads are supported on a lot of platforms
(in contrast to fork(), which is only available on POSIX systems). In
C/C++, you can use frameworks offering a single interface to the
underlying threading environment. In other languages such as Java or
Python, this interface is already bundled with the language itself.

Sebastian
 
J

Joachim Schmitz

(e-mail address removed) writes:

[...]> fork() is known to be the process creation equivalent to
threads
creation, and it provides most of the flexibility that threading
does. However, fork() is less efficient that threads, and much less
portable than threads (since it's only supported on POSIX systems),
so even when fork() is available, threads are not redundant.

[...]

fork() is less portable than threads? Huh?

What do you mean?

Well, strictly speaking, in C, threads are as portable as fork()
(i.e., non-portable), since they're not supported by ISO and you'll
need to rely on system-specific functionality in order to use either
one of them. As far as for POSIX, they're also equivalently portable:
any POSIX system supports both fork() and pthreads.

Huh? I don't think so. There are POSIX threads, yes, but in a different
POSIX standard as fork().
But what I mean is that threads are supported on a lot of platforms
(in contrast to fork(), which is only available on POSIX systems). In
C/C++, you can use frameworks offering a single interface to the
underlying threading environment. In other languages such as Java or
Python, this interface is already bundled with the language itself.

I'd bet that there are more system supporting POIX for then there are
supporting POSIX threads.
Sebastian

Bye, Jojo
 
J

Joachim Schmitz

Joachim said:
(e-mail address removed) writes:

[...]> fork() is known to be the process creation equivalent to
threads
creation, and it provides most of the flexibility that threading
does. However, fork() is less efficient that threads, and much less
portable than threads (since it's only supported on POSIX systems),
so even when fork() is available, threads are not redundant.

[...]

fork() is less portable than threads? Huh?

What do you mean?

Well, strictly speaking, in C, threads are as portable as fork()
(i.e., non-portable), since they're not supported by ISO and you'll
need to rely on system-specific functionality in order to use either
one of them. As far as for POSIX, they're also equivalently portable:
any POSIX system supports both fork() and pthreads.

Huh? I don't think so. There are POSIX threads, yes, but in a
different POSIX standard as fork().
But what I mean is that threads are supported on a lot of platforms
(in contrast to fork(), which is only available on POSIX systems). In
C/C++, you can use frameworks offering a single interface to the
underlying threading environment. In other languages such as Java or
Python, this interface is already bundled with the language itself.

I'd bet that there are more system supporting POIX for then there are
supporting POSIX threads.

Typos, sorry, should read:
 
S

s0suk3

Keith Thompson said:
fork() is known to be the process creation equivalent to threads
creation, and it provides most of the flexibility that threading does.
However, fork() is less efficient that threads, and much less portable
than threads (since it's only supported on POSIX systems), so even
when fork() is available, threads are not redundant. [...]

fork() is less portable than threads?  Huh?

Bearing in mind that Sebastian is on record as having encountered only
three (I think) installations of C ever, it is possible that *within his
own experience* his observation is accurate.

But I was trying to account for all platforms in general. If you think
that what I said isn't accurate outside personal experiences (which
have no practical value), stop with the word games and just say so.

Sebastian
 
S

s0suk3

(e-mail address removed) said:




So when you say "less portable than", you mean "as portable as"? Odd.

When I said "less portable than" in my first post, I was speaking
generally. Then I said "as portable as", qualifying it with the phrase
"strictly speaking". Those are two different contexts.
The fact that threads are supported on Platform A and Platform B doesn't
make threaded code portable between A and B *unless* the same interface
and semantics are available on both platforms. This is by no means always
the case.

And what on earth is stopping you from using a portable interface?
If you really need to use threads, that's obviously a good way to go. But
of course most programs would be better off without them.

Either you need them or you don't, of course. I'm just saying that
they have significant advantages over processes in general.

Sebastian
 
S

s0suk3

(e-mail address removed) said:

I did say so, pretty much, and I wasn't playing word games. But I disagree
that personal experiences have no practical value. On the contrary, they
have enormous practical value. But they are not always as mappable onto
other people's experiences as we might think.

In my own personal experience, neither fork() nor threads are especially
portable, and to argue about which is *more* portable seems to me to be an
angels-on-pinheads discussion.

Then you haven't used anything but C. Like I said earlier, there are
languages such as Python and Java that try to provide portable
interfaces to operating system services. On such languages, you'll be
able to write a portable threading application (without having to rely
on third-party libraries) that will work on any system where there is
an implementation of the language and that supports threads. The same
is not possible with fork(), since it's only available on POSIX
systems.

Sebastian
 
S

s0suk3

(e-mail address removed) said:



Partly non-availability. There isn't an interface that's portable *enough*.

Perhaps one of the best I've seen is Mozilla's NSPR.
And partly common sense. Threads were invented for people who can't write
state machines (which, incidentally, are far easier to debug).

Do state machines really have anything to do with parallel processing?
That sounds like a factoid to me (like the factoid that "integer operations
are faster than floating-point operations"). And threads have significant
*dis*advantages that should not be glossed over.

That would sound much more convincing if you stated what disadvantages
those are, and how you can avoid them using processes or state
machines.

Sebastian
 
S

s0suk3

(e-mail address removed) said:

Yes, they try. And surprisingly often they succeed. But if you think that
Python and Java are more portable than C, you have an astoundingly limited
view of computing.

Those languages are portable in a different sense than C is. C tries
to be portable across a wide range of platforms at the cost of failing
to provide many system services that may not be available under those
platforms, which greatly reduces its usability. Java and Python try to
be portable across a wide range of platforms while still providing
interfaces to as many system services as possible, at the cost of
being unable to provide those services on systems where they're not
available, and thus creating ambiguities in the interfaces on those
systems.

Unfortunately, we don't have both of those meanings of portability in
a single language yet.

Sebastian
 
N

Nick Keighley

no one said "if you don't use threads then use processes". Why not use
neither of them?
<off-topic>
My guess is that threads are often more bother than they are worth.

Given the possibility of programmed creation of processes (i.e. an api to
launch processes), threads are redundant.

well, no. If you *have to have parralleism" (and I'd argue the average
application has a lot less of it than some people think) then
processes
can be very heavy weight. I worked on a system that scaled badly.
It started so many processes it took *hours* to start.

In many environments, threads do not provide any execution-speed advantage
over processes (the usual "big" argument for threads is that "the
context-switch overhead for a thread is 'less' than the context-switch
overhead for a process", but in many systems, threads and processes have
the same context-switch overhead).

Threads usually require a greater level of programming support than
processes.

Programs that use threads often suffer from poor design/implementation,
causing any advantage that threads offer to be lost (I'm thinking of
deadlock and race conditions, and of failure to disentangle logic).

There are as effective ways of data sharing for processes as there are for
threads, and inter-process data sharing usually enforces a level of data
protection that inter-thread data sharing avoids.

and this is *all* avoided if you use neitehr threads no processes.
 
N

Nick Keighley

fork() is known to be the process creation equivalent to threads
creation, and it provides most of the flexibility that threading does.
However, fork() is less efficient that threads, and much less portable
than threads (since it's only supported on POSIX systems),

you are comparing oranges with orchards.

threads and processes are the things to compare. fork()
is just one OS specific way of creating processes.
Compare like with like if you are going to talk portability.


so even
when fork() is available, threads are not redundant. When fork() is
not available, you can only rely on creation of external processes,
which are much less flexible (e.g., there are less mechanisms for IPC)
and less efficient than threads.

why? Why are fork-less system less flexible. What is the connection
between process creation and IPC?

That has nothing to do with threads themselves. Maybe you've seen a
lot of such applications, but they're poor design is purely their
implementors' fault.

fair point. People can write crap in any language.
Tho' threads are pretty easy to make mistakes with...

<snip>
 
A

Antoninus Twink

fork() is known to be the process creation equivalent to threads
creation, and it provides most of the flexibility that threading does.
However, fork() is less efficient that threads, and much less portable
than threads (since it's only supported on POSIX systems), so even
when fork() is available, threads are not redundant. When fork() is
not available, you can only rely on creation of external processes,
which are much less flexible (e.g., there are less mechanisms for IPC)
and less efficient than threads.

I don't really agree with this assessment.

I'd say that for communication purposes, fork()ed processes are much
less flexible than threads, and an external process provides most of the
flexibility of a fork()ed process.

OK, so you have some nice conveniences with fork() like being able to
open a pipe, have the file descriptors copied to the child, then use it
for parent-to-child or child-to-parent communication, but IPC between a
parent and child process isn't really much easier or more convenient
than between two arbitrary processes.
 
S

s0suk3

(e-mail address removed) said:



Most people who use threads do so not because they need parallel
processing, but because they think they do. For example, it's commonplace
to see server code with one thread per client, which is a ludicrous misuse
of resources. In a great many cases, threads are simply not a good fit to
the problem. (This says nothing about their portability, of course.)

How do you propose writing a server that needs to handle multiple
clients synchronously without parallel processing? The only
alternative I've heard so far is select(), but it's only optimal if
the server isn't receiving too many requests.
If you don't know already, I see little value in continuing this
discussion. But that doesn't mean I'm ducking the question.

The most obvious disadvantage is that threads can compete over object
values. Thread A might try to read the value whilst Thread B is in the
middle of updating that value, for example. So you have to do the whole
semaphore/mutex thing. And you have to be careful to avoid a deadlock,
where Thread A has locked resource C and is waiting for resource D,
whereas Thread B has locked resource D and is waiting for resource C.

Writing thread-safe code is a far from trivial exercise. Writing a state
machine solution is much simpler and generally less bug-prone (at least,
in my experience).

I think writing thread-safe code is trivial once you adopt the set of
coding practices that lead to thread-safe code. Dealing with the
threads themselves may be less trivial, but it's the cost of having
the added functionality. Anyway, remember the old saying

"Keep it simple: as simple as possible, but no simpler."

I think you're trying to keep it simpler :)

Sebastian
 
S

s0suk3

I don't really agree with this assessment.

I'd say that for communication purposes, fork()ed processes are much
less flexible than threads,

Yes, that's what I said.
and an external process provides most of the
flexibility of a fork()ed process.

OK, so you have some nice conveniences with fork() like being able to
open a pipe, have the file descriptors copied to the child, then use it
for parent-to-child or child-to-parent communication, but IPC between a
parent and child process isn't really much easier or more convenient
than between two arbitrary processes.

How isn't it more easier or convenient if you have those mechanisms
available? With external processes, all you have are the standard I/O
streams connected as pipes between the processes. The OS may provide
more specialized IPC mechanisms (such as UNIX domain sockets, under
UNIX, or just Internet domain sockets connected to the loopback
interface), but these are very non-portable and usually lead to a
great increase in complexity.

Sebastian
 
I

Ian Collins

Richard said:
(e-mail address removed) said:

I have quite a few programs installed on this machine that were written by
people who think as you do. These programs crash rather often.
It's seldom trivial, but thread-safe programming is a skill well worth
mastering in these days of multi-core CPUs. I can't remember the last
time I used a single core desktop.

Would you be happy if the developers of your OS shared your Luddite
attitude and refused to build a threaded kernel?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,262
Messages
2,571,045
Members
48,769
Latest member
Clifft

Latest Threads

Top