问题
When writing threaded code in C, I first have to create some struct
which includes all the arguments and a wrapper function. This leads to lots of code bloat and is not easy to read. See:
struct some_function_args {
int arg1;
int arg2;
int arg3;
};
void some_function_wrapper(struct some_function_args* args) {
some_function(args->arg1, args->arg2, args->arg3);
}
int main() {
struct my_args;
my_args.arg1 = 1;
my_args.arg2 = 2;
my_args.arg3 = 3;
pthread_create(..., some_function_wrapper, &my_args);
pthread_join(...);
}
Is there some kind of macro or library (maybe using varargs
) which automatically creates the needed structs and wrapper functions for me, like this? Or is this not possible at all in C?
int main() {
MY_THREAD thread = IN_THREAD {
some_function(1, 2, 3);
}
JOIN_THREAD(thread);
}
回答1:
EDIT: I released some code. See threadify.h.
With the following macros you can do things like this:
char a = 'A';
int b = 23;
char[] c = "Example";
pthread_t thread;
// THREAD3 because it takes 3 arguments of variable type.
THREAD3(thread, a, b, c, {
printf("test: %c %d %s\n", a, b, c);
});
JOIN(thread);
It's possible in GCC, because GCC has two non-standard extensions:
- nested functions
- The
typeof()
operator
There are some drawbacks in this huge mess of macros:
- You cannot pass rvalues (because it's not possible to create pointers to them)
You need to use the appropriate
THREAD0
,THREAD1
, ... macro depending on the number of arguments (not sure if it's possible to work around this using variadic macros).#include <stdio.h> #include <pthread.h> // Nested definition to work around preprocessor prescan #define __CAT(arg1, arg2) arg1 ## arg2 #define CAT(arg1, arg2) __CAT(arg1, arg2) // Use the current line number to create a unique name for objects #define NAME(arg1) CAT(arg1, __LINE__) // Creates a thread without any arguments #define THREAD0(thread, code) \ void NAME(__pthread_wrapper)(void) {\ do {code;} while(0); \ }; \ pthread_create(&thread, NULL, (void*)NAME(__pthread_wrapper), NULL); // Creates a thread with one argument by creating a struct // and passing all values via this struct. #define THREAD1(thread, arg1, code) \ typedef struct { \ typeof(arg1)* NAME(__pthread_arg1); \ } NAME(__pthread_struct); \ void NAME(__pthread_wrapper)(NAME(__pthread_struct)* data) {\ do {code;} while(0); \ }; \ NAME(__pthread_struct) NAME(__data); \ NAME(__data).NAME(__pthread_arg1) = &arg1; \ pthread_create(&thread, NULL, (void*)NAME(__pthread_wrapper), &NAME(__data)); #define THREAD2(thread, arg1, arg2, code) \ typedef struct { \ typeof(arg1)* NAME(__pthread_arg1); \ typeof(arg2)* NAME(__pthread_arg2); \ } NAME(__pthread_struct); \ void NAME(__pthread_wrapper)(NAME(__pthread_struct)* data) {\ do {code;} while(0); \ }; \ NAME(__pthread_struct) NAME(__data); \ NAME(__data).NAME(__pthread_arg1) = &arg1; \ NAME(__data).NAME(__pthread_arg2) = &arg2; \ pthread_create(&thread, NULL, (void*)NAME(__pthread_wrapper), &NAME(__data)); #define THREAD3(thread, arg1, arg2, arg3, code) \ typedef struct { \ typeof(arg1)* NAME(__pthread_arg1); \ typeof(arg2)* NAME(__pthread_arg2); \ typeof(arg3)* NAME(__pthread_arg3); \ } NAME(__pthread_struct); \ void NAME(__pthread_wrapper)(NAME(__pthread_struct)* data) {\ do {code;} while(0); \ }; \ NAME(__pthread_struct) NAME(__data); \ NAME(__data).NAME(__pthread_arg1) = &arg1; \ NAME(__data).NAME(__pthread_arg2) = &arg2; \ NAME(__data).NAME(__pthread_arg3) = &arg3; \ pthread_create(&thread, NULL, (void*)NAME(__pthread_wrapper), &NAME(__data)); /* THREAD4, THREAD5, ... */ #define JOIN(thread) pthread_join(thread, NULL);
回答2:
'When writing threaded code in C, I first have to create some struct which includes all the arguments and a wrapper function. This leads to lots of code bloat and is not easy to read'. Sure. That's what you pay for making your app, (assuming it's not stupid), either X times faster or X times easier to implement becasue it's easier described as independent functionality. You want something for nothing?
来源:https://stackoverflow.com/questions/28330956/how-to-avoid-code-bloat-when-using-pthreads-in-c