Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Simple threads question

2 views
Skip to first unread message

Patrick Riphagen

unread,
Aug 21, 2001, 5:12:10 AM8/21/01
to
Hello all,

At work, I'm trying to run the same filter multiple times. (Run the same
filter 5 times for 5 files or later for 5 sensors).
My idea was to create a seperate thread that run the same filter for each
input. This filter is an ANSI C part wich contains some global functions.
Should it be possible to execute these 5 threads completely independently or
are there some conditions to this. (Are global (shared) functions a
problem?)

Thank you in advance

Patrick Riphagen


Attila Feher

unread,
Aug 21, 2001, 5:39:40 AM8/21/01
to

Not the functions I guess, but if they do use any "static" data (like
buffers). Eg:

This is problem:

const char *gimmeString( int which) {
char stringOf[4000];
fillString( &stringOf, which);
return stringOf;
}

This is not a problem:

int gimmeString( char *target, size_t buffsize, int which) {
int success=1;
// Here is the work
return success;
}

A

Patrick Riphagen

unread,
Aug 21, 2001, 8:25:21 AM8/21/01
to
> Patrick Riphagen wrote:
> >
> > Hello all,
> >
> > At work, I'm trying to run the same filter multiple times. (Run the same
> > filter 5 times for 5 files or later for 5 sensors).
> > My idea was to create a seperate thread that run the same filter for
each
> > input. This filter is an ANSI C part wich contains some global
functions.
> > Should it be possible to execute these 5 threads completely
independently or
> > are there some conditions to this. (Are global (shared) functions a
> > problem?)
>
> Not the functions I guess, but if they do use any "static" data (like
> buffers). Eg:
>


Thanks, but I'm not using any globals or statics (exept the functions, which
are included in the Class)
I used to do this but I converted them to local variables. Still if I run
the threads at the same time, the results defer slightly ( 10EXP-5 order)
They seem to be interfering, but there not using each others variables for
as far as I can see, any more suggestions on how they can be using some
shared memory or something like that?

Patrick


dan wanderer

unread,
Aug 21, 2001, 8:34:47 AM8/21/01
to
See inline

"Attila Feher" <Attila...@lmf.ericsson.se> wrote in message news:3B822C5C...@lmf.ericsson.se...


> Patrick Riphagen wrote:
> >
> > Hello all,
> >
> > At work, I'm trying to run the same filter multiple times. (Run the same
> > filter 5 times for 5 files or later for 5 sensors).
> > My idea was to create a seperate thread that run the same filter for each
> > input. This filter is an ANSI C part wich contains some global functions.
> > Should it be possible to execute these 5 threads completely independently or
> > are there some conditions to this. (Are global (shared) functions a
> > problem?)
>
> Not the functions I guess, but if they do use any "static" data (like
> buffers). Eg:
>
> This is problem:
>
> const char *gimmeString( int which) {
> char stringOf[4000];
> fillString( &stringOf, which);
> return stringOf;
> }
>

This is a problem only because you return a pointer into the stack. It won't work
reguardless of threading ;)

This won't work in multiple threads:

const char *gimmeString( int which ) {
static char stringOf[4000];
fillString( stringOf, which);
return stringOf;
}

because the stringOf buffer is static, all threads see the same one.

> This is not a problem:
>
> int gimmeString( char *target, size_t buffsize, int which) {
> int success=1;
> // Here is the work
> return success;
> }
>
> A

Global functions are all right, global data is not. Check the filter code to make sure there
are no globally declared variables, including static declarations inside functions.
You _can_ use global variables, just protect access to them with a mutex or critical section.

Dan

Patrick Riphagen

unread,
Aug 21, 2001, 11:25:25 AM8/21/01
to
> because the stringOf buffer is static, all threads see the same one.
>
Thanks!! I still used 1 static variable, to count if first 300 samples had
past, (function is exited every sample). Removing this one did the trick.

>
> Global functions are all right, global data is not. Check the filter code
to make sure there
> are no globally declared variables, including static declarations inside
functions.
> You _can_ use global variables, just protect access to them with a mutex
or critical section.
>

I'd like to use global variables, but they should be global for 1 thread,
not global for the entire app.
So I need some kind of "thread-globals". Is there a way of accomplishing
this?
Now I pass all formely global variables as function arguments within each
thread, but I'm not really fond of this solution, other possibilities?

Patrick


Kaz Kylheku

unread,
Aug 21, 2001, 11:52:06 AM8/21/01
to
In article <9ltuh8$j6k$1...@news.btcnet.nl>, Patrick Riphagen wrote:
>> because the stringOf buffer is static, all threads see the same one.
>>
>Thanks!! I still used 1 static variable, to count if first 300 samples had
>past, (function is exited every sample). Removing this one did the trick.
>
>>
>> Global functions are all right, global data is not. Check the filter code
>to make sure there
>> are no globally declared variables, including static declarations inside
>functions.
>> You _can_ use global variables, just protect access to them with a mutex
>or critical section.
>>
>
>I'd like to use global variables, but they should be global for 1 thread,
>not global for the entire app.
>So I need some kind of "thread-globals". Is there a way of accomplishing
>this?

There are platform-specific ways to associate objects with threads. Under
POSIX, you have the functions pthread_key_create, pthread_key_destroy,
pthread_getspecific and pthread_setspecific.

There is nothing comparable under Win32. The TlsAlloc function and related
functions look superficially similar but they lead to memory leaks,
because there is no way to associate a destructor with a thread-specific
object which is called when the thread terminates. (But if you are writing
a DLL, you can hook this destruction to the DllMain(DLL_THREAD_DETACH)
call).

The Microserfs clearly didn't read the POSIX documentation carefully
enough before they cloned the functionality. ;)

>Now I pass all formely global variables as function arguments within each
>thread, but I'm not really fond of this solution, other possibilities?

The real solution to this are dynamically scoped variables, in languages
like Lisp. In fact, this is such a useful language feature, that it's worth
emulating.

Briefly, a dynamically scoped variable is one whose reference is resolved
by considering the activation chain in which the reference is made.
The variable can be bound somewhere in the activation chain; if it isn't,
then a global value is retrieved. (Under threads, that global value
should be thread-specific).

The dynamic resolution means that a function can redefine a local version
of the variable before calling another function. That called function
will then access the local version rather than the global one; effectively
the local binding shadows the global one.

If C had dynamically scoped variables, it would look something like this:

#include <stdio.h>

int x = 3; /* global one */

void foo()
{
printf("x = %d\n", x);
}


void bar()
{
dynamic int x = 4; /* fictitious keyword, ``dynamic'' */
foo(); /* foo will now print 4, not 3 */
}

int main(void)
{
foo(); /* foo will print 3 */
bar();
return 0;
}

So, effectively, the behavior is as if you were passing the entire set
of dynamic variables into every function, allowing you to pass down
arbitrary state information, without having to explicitly do so
in the argument list. It's a kind of taming of global variables.

David Schwartz

unread,
Aug 21, 2001, 12:14:27 PM8/21/01
to
Patrick Riphagen wrote:

> Now I pass all formely global variables as function arguments within each
> thread, but I'm not really fond of this solution, other possibilities?

Why aren't you fond of it? This is really what you mean, isn't it?

DS

Patrick Riphagen

unread,
Aug 22, 2001, 4:39:19 AM8/22/01
to
I'm not fond of it because I don't like long parameter lists when not
necessary and I thought maybe it causes lots of overhead or unnecessary
copying of parameters in memory

P


Arnold Hendriks

unread,
Aug 22, 2001, 5:04:02 AM8/22/01
to
Define 'long'. You're probably usually wasting much more stack space
on local variables than on passed arguments. But if that is the problem,
you can store all data you want to pass inside a struct, and pass a pointer
to that structure as an argument to the function

--
Arnold Hendriks <a.hen...@b-lex.com>
B-Lex Information Technologies, http://www.b-lex.com/

Chris Sheppard

unread,
Aug 22, 2001, 4:39:53 PM8/22/01
to
Instead of globals, you could make them thread-globals, using
thread-specific storage. Not sure if this is a 'better' solution or
not.....

Chris

Charles Bryant

unread,
Aug 23, 2001, 8:57:08 PM8/23/01
to
In article <3B841899...@quack.com>,
Chris Sheppard <ch...@quack.com> wrote:

>Patrick Riphagen wrote:
>>
>> Now I pass all formely global variables as function arguments within each
>> thread, but I'm not really fond of this solution, other possibilities?
>>
>Instead of globals, you could make them thread-globals, using
>thread-specific storage. Not sure if this is a 'better' solution or
>not.....

No. It's terrible. The idea of passing parameters in global variables is
fundamentally bad. It makes the software gratuitously difficult to
understand, by making it very difficult to track down all the places
where they are updated and used. This is what scoping rules are
intended to facilitate.

Even if there was no other reason to avoid the technique, it is quite
possible that access to thread-specific storage is less efficient
than any other type of access, and it is highly likely that it is
less efficient than access to ordinary parameters. For example, on
the SPARC processor, parameters are passed in registers, so even if
thread-specific storage is implemented by allocating a global
register to point to the thread-specific storage area, loading and
storing each value will take extra memory accesses.

--
Eppur si muove

Alexander Terekhov

unread,
Aug 24, 2001, 4:41:29 AM8/24/01
to

without TSD:

A( thread_name ) // A does not need thread_name; calls B
B( thread_name ) // B does not need thread_name; calls C
C( thread_name ) // C does not need thread_name; calls D
.
.
.
Z( thread_name ) {
// lock resource X
...
// trace/log thread_name, X, "work_beg", time
...
// do some work using locked resource X
...
// trace/log thread_name, X, "work_end", time
...
// unlock resources X
...
}

with TSD:

static tsd_key thread_name_key;

A( thread_name ) // A saves thread_name and calls B
// without thread_name arg
once_init( &thread_name_key )
tsd_set( thread_name_key,thread_name )
B() // B calls C without thread_name arg
C() // C calls D without thread_name arg
.
.
.
Z() {
thread_name = tsd_get( thread_name_key );
// lock resources X
...
// trace/log thread_name, X, "work_beg", time
...
// do some work using locked resource X
...
// trace/log thread_name, X, "work_end", time
...
// unlock resources X
...
}

regards,
alexander.

Charles Bryant

unread,
Aug 27, 2001, 10:06:25 PM8/27/01
to
In article <3B861339...@web.de>,
Alexander Terekhov <tere...@web.de> wrote:

I'm not entirely sure what point you are trying to make, but I think
this is a classic abuse of thread-specific data. It seems to arise
from a fundamental misconception about what threads should be: they
are not objects - they act on objects, so a program shouldn't care
which thread does an item of work, so it should have no need to know
which thread is running at any point. Obviously test and debugging
doesn't follow this rule, just as it doesn't follow any other rules
for good design.

--
Eppur si muove

Marc A. Power

unread,
Aug 30, 2001, 2:59:07 PM8/30/01
to
> I'm not entirely sure what point you are trying to make, but I think
> this is a classic abuse of thread-specific data.

What precisely are proper uses of TSD? When is its use called for and when
is it not?

Thank you,

Marc


Charles Bryant

unread,
Aug 30, 2001, 9:22:15 PM8/30/01
to
In article <9mm2ds$nut$1...@news.artemis.com>,

Marc A. Power <mar...@hotmail.com> wrote:
>What precisely are proper uses of TSD? When is its use called for and when
>is it not?

It's most important use is the implementation of misdesigned
interfaces which cannot be changed. For example, the really bad
strtok() which saves an argument you pass in and re-uses it at
subsequent calls. Another well-known example is the implementation of
errno, which obviously must be different in each thread. While the
loss of strtok() would be quite beneficial, errno is just too deeply
entrenched to get eliminated.

--
Eppur si muove

0 new messages