Macro for pthread_create()

D

daniele.g

For code portability I need to write a macro THREAD(func, param) which
must be resolved into pthread_create(&func_id, NULL, func, (void *)
param)

I wrote this:

#define THREAD(func,parm) (pthread_create(&func, NULL, func, (void *)
parm))

But it doesn't work. Any clue?

Thanks in advance.
 
J

Jens Thoms Toerring

daniele.g said:
For code portability I need to write a macro THREAD(func, param) which
must be resolved into pthread_create(&func_id, NULL, func, (void *)
param)
I wrote this:
#define THREAD(func,parm) (pthread_create(&func, NULL, func, (void *)
parm))
But it doesn't work. Any clue?

pthread_create() takes (at least in the POSIX version) a
pointer to a pthred_t variable (that can't be NULL and must
be an address the function can write to) as its first ar-
gument, not a function (and also not a pointer to the
pointer to the function to be called). So this macro
can't "work". And what has using such a macro to do with
"portability"?
Regards, Jens
 
J

James Kuyper

For code portability I need to write a macro THREAD(func, param) which
must be resolved into pthread_create(&func_id, NULL, func, (void *)
param)

Where does func_id come from?
I wrote this:

#define THREAD(func,parm) (pthread_create(&func, NULL, func, (void *)
parm))

There's no func_id in the expansion of that macro.

pthread_create() isn't part of the C standard library. As far as this
newsgroup is concerned, it could be anything, and the correct answer to
your question depends upon precisely how pthead_create is declared.
comp.programming.unix would be a more appropriate forum for such a question.
But it doesn't work. Any clue?

What exactly does "doesn't work" mean? Before you post to
comp.programming.unix, create a simplified version of your program, as
small as possible, which demonstrates the problem. Do a test build and
run to make sure it actually demonstrates the problem. Give them the
exact text of the program that failed. Tell them precisely which
compiler you're using, the command line options you used, and precisely
what error messages, if any, you got when you compiled and linked it. If
"doesn't work" refers to something that happens when you run the
program, after successfully compiling and linking it, then tell them
precisely what input you gave the program, and what precisely the output
was that convinced you that "it doesn't work".
 
S

Seebs

For code portability I need to write a macro THREAD(func, param) which
must be resolved into pthread_create(&func_id, NULL, func, (void *)
param)
I wrote this:
#define THREAD(func,parm) (pthread_create(&func, NULL, func, (void *)
parm))
But it doesn't work. Any clue?

Nope.

Suggestion: Maybe you should expand a little on "doesn't work". You
might have meant:
I get a compiler error.
My program crashes.
I looked at preprocessed output and it wasn't what I expected.

The obvious thing that leaps out at me is that you say you want
pthread_create(&func_id, NULL, func, (void *) param)
but you wrote
pthread_create(&func, NULL, func, (void *) param)

which makes me wonder whether you actually wanted the _id, and if so,
why you omitted it. You may be looking for the "token pasting" operator,
##. See the comp.lang.c FAQ for more info on that.

-s
 
J

Jens Thoms Toerring

pthread_create() takes (at least in the POSIX version) a
pointer to a pthred_t variable (that can't be NULL and must
be an address the function can write to) as its first ar-
gument, not a function (and also not a pointer to the
pointer to the function to be called). So this macro
can't "work". And what has using such a macro to do with
"portability"?

Sorry, I overlooked that it's 'func_id' in what you want the
macro to expand to. With that I can only guess at your inten-
tions: do you always have a variable for the thread ID (i.e.
the first argument) that has the same name as the function,
but with '_id' appended to it? In that case you could try

#define THREAD(func,parm) pthread_create(&#func_id, NULL, func, (void *) parm)

(assuming that your compiler understands the concatenation
bit '##', which is, as far as I remember from C99).

With this

THREAD( a, b )

should expand to

pthread_create(&a_id, NULL, a, (void *) b)

Regards, Jens
 
B

Ben Bacarisse

Sorry, I overlooked that it's 'func_id' in what you want the
macro to expand to. With that I can only guess at your inten-
tions: do you always have a variable for the thread ID (i.e.
the first argument) that has the same name as the function,
but with '_id' appended to it? In that case you could try

#define THREAD(func,parm) pthread_create(&#func_id, NULL, func, (void *) parm)

(assuming that your compiler understands the concatenation
bit '##', which is, as far as I remember from C99).

It's as old as C89 ("ANSI C") and you've got a typo in the macro. You
presumable wanted to write:

#define THREAD(func,parm) \
pthread_create(&func ## _id, NULL, func, (void *)parm)

<snip>
 
S

Seebs

Where does func_id come from?

My guess is that the intent is that if you call THREAD(foo, bar), the OP
wants
pthread_create(&foo_id, NULL, foo, (void *) bar);
pthread_create() isn't part of the C standard library. As far as this
newsgroup is concerned, it could be anything, and the correct answer to
your question depends upon precisely how pthead_create is declared.

I am not sure of that -- so far as I can tell, this one's purely a textual
representation question about the preprocessing phases.

-s
 
J

Jens Thoms Toerring

It's as old as C89 ("ANSI C")

Thanks, had somehow associated it with C99.
and you've got a typo in the macro. You presumable wanted
to write:
#define THREAD(func,parm) \
pthread_create(&func ## _id, NULL, func, (void *)parm)

Uups, yes, of course! I thought I had copy-and-paste'd it from
my test program but I seem to have screwed that up:-(

Best regards, Jens
 
D

daniele.g

Seebs said:
The obvious thing that leaps out at me is that you say you want
pthread_create(&func_id, NULL, func, (void *) param)
but you wrote
pthread_create(&func, NULL, func, (void *) param)

Which makes me wonder whether you actually wanted the _id, and if so,
why you omitted it. You may be looking for the "token pasting" operator,
##. See the comp.lang.c FAQ for more info on that.

Yur're right, I wrote wrong the macro expansion.
What I want is that when I compile this source under linux the macro is
translated into the pthread_create(...) function, knowing that the macro
has only two parameters. My problem is that I don't know how to create
dinamically a func_id to be inserted into the macro definition.
 
B

Ben Bacarisse

Yur're right, I wrote wrong the macro expansion.
What I want is that when I compile this source under linux the macro is
translated into the pthread_create(...) function, knowing that the macro
has only two parameters. My problem is that I don't know how to create
dinamically a func_id to be inserted into the macro definition.

If there is a fixed, textual, relationship between "func" and "func_id"
(i.e. the first parameter is always the third but with _id added to the
name) then the token pasting macro already posted (it uses "func ## _id"
in the body) will do the trick.
 
J

Jens Thoms Toerring

Yur're right, I wrote wrong the macro expansion.
What I want is that when I compile this source under linux the macro is
translated into the pthread_create(...) function, knowing that the macro
has only two parameters. My problem is that I don't know how to create
dinamically a func_id to be inserted into the macro definition.

If you never need to use the thread ID (i.e. what's returned via
the first argument) perhaps this is what you're looking for:

#define THREAD( func, parm ) \
{ pthread_t thread_id; \
pthread_create( &thread_id, NULL, func, ( void * ) ( parm ) ); }

The curly braces are just there for restricting the life-time
of the 'thread_id' variable (it "goes out of scope" at the
closing '}').

But if you need the thread ID later on then I guess you will
have to explain in more detail what this is all about (or what
you exactly mean with "dynamically create a func_id").

Regards, Jens
 
E

Eric Sosman

[...]
Yur're right, I wrote wrong the macro expansion.
What I want is that when I compile this source under linux the macro is
translated into the pthread_create(...) function, knowing that the macro
has only two parameters. My problem is that I don't know how to create
dinamically a func_id to be inserted into the macro definition.

You'd need to generate both the declaration and the use:

#define THREAD(func,parm) { \
pthread_t func ## _id; \
pthread_create(&func ## _id, NULL, func, (void*)(parm)); \
}

Under C99 or later, which allow variable declarations to be
intermixed with executable statements, you can get rid of the
curly braces.

<off-topic>

... but it's a dumb idea. The pthread_t variable is your only
"handle" for the new thread, something you'll need if you later
want to await the thread's completion or send it a signal or anything
of that kind. It's a vital part of the machinery, not something that
should be swept under the rug.

Also, the presence of the declaration means that the macro
expansion is no longer an expression (it's a declaration plus an
expression-statement, possibly wrapped in a compound statement).
Since it's not an expression it has no value, meaning that the value
returned by pthread_create() is simply lost: You have no way of
knowing whether thread creation succeeded or failed, and no clue
as to the cause of a failure.

Why do you think such a macro would be desirable?

</off-topic>
 
I

Ian Collins

Yur're right, I wrote wrong the macro expansion.
What I want is that when I compile this source under linux the macro is
translated into the pthread_create(...) function, knowing that the macro
has only two parameters. My problem is that I don't know how to create
dinamically a func_id to be inserted into the macro definition.

Why use a macro? It would be easier and clearer to use a function.
 
D

daniele.g

Eric Sosman said:
<Off-topic>

... But it's a dumb idea. The pthread_t variable is your only
"handle" for the new thread, something you'll need if you later
want to await the thread's completion or send it a signal or anything
of that kind. It's a vital part of the machinery, not something that
should be swept under the rug.

I do agree.
Also, the presence of the declaration means that the macro
expansion is no longer an expression (it's a declaration plus an
expression-statement, possibly wrapped in a compound statement).
Since it's not an expression it has no value, meaning that the value
returned by pthread_create() is simply lost: You have no way of
knowing whether thread creation succeeded or failed, and no clue
as to the cause of a failure.

Why do you think such a macro would be desirable?

That macro would be desiderable because I need to make it run under
Linux and another OS for embedded systems which doesn't support
pthreads. For now I want it run under Linux for testing. Maybe the macro
is badly defined, and need to be modified.
 
J

James Kuyper

I do agree.


That macro would be desiderable because I need to make it run under
Linux and another OS for embedded systems which doesn't support
pthreads. For now I want it run under Linux for testing. Maybe the macro
is badly defined, and need to be modified.

To understand why a macro is needed, it would help to know how you were
thinking of defining the macro for the other OS. It's possible that
providing two different function definitions, depending upon the OS
(possibly with two different declarations) might be clearer and safer
than providing two different macro definitions.

The macro as you've presented it has one clear advantage: it enforces a
naming convention connecting the function and and the thread id.
However, it might be better to maintain that connection by other means,
such as a structure containing both the thread id and a pointer to the
relevant function.
 
K

Keith Thompson

Ben Bacarisse said:
If there is a fixed, textual, relationship between "func" and "func_id"
(i.e. the first parameter is always the third but with _id added to the
name) then the token pasting macro already posted (it uses "func ## _id"
in the body) will do the trick.

Of course you have to declare "func" and "func_id", or "foo" and
"foo_id", or ....
 
K

Keith Thompson

If you never need to use the thread ID (i.e. what's returned via
the first argument) perhaps this is what you're looking for:

#define THREAD( func, parm ) \
{ pthread_t thread_id; \
pthread_create( &thread_id, NULL, func, ( void * ) ( parm ) ); }

The curly braces are just there for restricting the life-time
of the 'thread_id' variable (it "goes out of scope" at the
closing '}').
[...]

A macro that expands to a statement should use the "do { ... } while
(0)" idiom:

#define THREAD( func, parm ) \
do { \
pthread_t thread_id; \
pthread_create( &thread_id, NULL, (func), ( void * ) ( parm ) ); \
while (0)
 
E

Eric Sosman

Eric Sosman said:
[...]
Why do you think such a macro would be desirable?

That macro would be desiderable because I need to make it run under
Linux and another OS for embedded systems which doesn't support
pthreads. For now I want it run under Linux for testing. Maybe the macro
is badly defined, and need to be modified.

It seems likely that simulating threads on an unthreaded
system (or even just doing without them) will involve more changes
to your program than you can easily encapsulate in a macro. The
purely-C question of how to write the macro has been answered, but
the beyond-C issues of managing the threading aren't really this
forum's business[*]. Try comp.programming.threads.

[*] The latest "C11" edition of the C Standard defines threading
support for C, so at least some threading questions will eventually
become topical here. But C11 is so fresh from the womb that its eyes
aren't yet open, so it'll be a while before you can find C11-conforming
implementations or get reliable advice on using them.
 
D

daniele.g

Ian Collins said:
Why use a macro? It would be easier and clearer to use a function.

How? I mean: in Linux I can simply write:

#include <pthread.h>
....
pthread_create( ... );

in OS20 I can't since it doesn't have them, so my idea is to make a
conditional compiling using a macro. Am I right?
 
I

Ian Collins

How? I mean: in Linux I can simply write:

#include<pthread.h>
....
pthread_create( ... );

in OS20 I can't since it doesn't have them, so my idea is to make a
conditional compiling using a macro. Am I right?

So on a POSIX platform, include <pthread.h>, for others write your own
versions of the threading functions.

Something like

#if defined HAVE_PTHREADS
# include <pthread.h>
#else
# if defined SOME_OS
typedef int pthread_t;
typedef struct { /* supported options */ } pthread_attr_t;
int pthread_create( pthread_t *restrict thread,
const pthread_attr_t* restrict attr,
void* (*start_routine)(void*), void* restrict arg );
# endif
#endif
 

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
473,755
Messages
2,569,536
Members
45,011
Latest member
AjaUqq1950

Latest Threads

Top