在 C 中使用 pthreads 时如何避免代码膨胀?
How to avoid code bloat when using pthreads in C?
在用 C 编写线程代码时,我首先必须创建一些 struct
,其中包括所有参数和包装函数。这会导致大量代码膨胀并且不易阅读。参见:
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(...);
}
是否有某种宏或库(可能使用 varargs
)可以自动为我创建所需的结构和包装函数,就像这样?或者这在 C 中根本不可能吗?
int main() {
MY_THREAD thread = IN_THREAD {
some_function(1, 2, 3);
}
JOIN_THREAD(thread);
}
EDIT: I released some code. See threadify.h.
使用以下宏,您可以执行以下操作:
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);
在 GCC 中是可能的,因为 GCC 有两个非标准扩展:
- 嵌套函数
typeof()
运算符
这一大堆宏有一些缺点:
- 您不能传递右值(因为无法创建指向它们的指针)
您需要使用适当的 THREAD0
、THREAD1
、...宏,具体取决于参数的数量(不确定是否可以使用可变参数解决此问题宏)。
#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);
'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'。当然。这就是你为制作你的应用程序所付出的代价,(假设它并不愚蠢),要么快 X 倍,要么更容易实施 X 倍,因为它更容易被描述为独立功能。你想要免费的东西吗?
在用 C 编写线程代码时,我首先必须创建一些 struct
,其中包括所有参数和包装函数。这会导致大量代码膨胀并且不易阅读。参见:
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(...);
}
是否有某种宏或库(可能使用 varargs
)可以自动为我创建所需的结构和包装函数,就像这样?或者这在 C 中根本不可能吗?
int main() {
MY_THREAD thread = IN_THREAD {
some_function(1, 2, 3);
}
JOIN_THREAD(thread);
}
EDIT: I released some code. See threadify.h.
使用以下宏,您可以执行以下操作:
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);
在 GCC 中是可能的,因为 GCC 有两个非标准扩展:
- 嵌套函数
typeof()
运算符
这一大堆宏有一些缺点:
- 您不能传递右值(因为无法创建指向它们的指针)
您需要使用适当的
THREAD0
、THREAD1
、...宏,具体取决于参数的数量(不确定是否可以使用可变参数解决此问题宏)。#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);
'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'。当然。这就是你为制作你的应用程序所付出的代价,(假设它并不愚蠢),要么快 X 倍,要么更容易实施 X 倍,因为它更容易被描述为独立功能。你想要免费的东西吗?