2015-02-04 37 views
1

在C編寫線程代碼時,我首先必須創建一些包含所有參數和包裝函數的struct。這導致大量的代碼膨脹並且不容易閱讀。請參閱:在C中使用pthreads時如何避免代碼膨脹?

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); 
} 
+1

請注意,'some_function_wrapper'應該帶一個'void *'並明確地將它轉換爲'struct some_function_args *'。否則,它會被調用錯誤的原型,這是未定義的行爲。 – Quentin

+0

較新的C標準(C99)有複合初始值設定項:'struct my_args = {.arg1 = 1,.arg2 = 2,.arg3 = 3};' – EOF

回答

0

編輯:我發佈了一些代碼。請參閱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()運營商

有一些缺點在這個巨大的宏混亂:

  • 你不能傳遞右值(因爲它無法創建指向它們的指針)
  • 您需要使用適當的THREAD0THREAD1,...宏取決於參數的數量(不知道是否可以使用可變宏來解決這個問題)。

    #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); 
    
+1

也許你可以在一對圓括號中分隔參數:''線程(線程,(a,b,c),{...})'?我不是PP大師,但我在Boost看到了瘋狂的東西,這看起來基本夠用。 – Quentin

+0

然後我仍然需要通過它們迭代來創建結構。也許我可以使用以下技術在(a,b,c)'循環中構建一些'#for VAR':http://stackoverflow.com/a/10542793/773690 – iblue

+1

Boost PP在這裏可能會很有用。也請看看[我上面的評論](http://stackoverflow.com/questions/28330956/how-to-avoid-code-bloat-when-using-pthreads-in-c/28332447#comment45010969_28330956)關於函數指針。這種方式可能會起作用,但更符合標準要求而不是抱歉。 – Quentin

-1

「當在寫C線程代碼,我首先必須創建一些結構,其中包括所有的參數和一個包裝函數。這導致大量的代碼膨脹並且不容易閱讀'。當然。這就是您爲製作應用所付出的代價(假設它不是愚蠢的),要麼快X倍,要麼X倍更容易實現,因爲它更容易描述爲獨立功能。你想要什麼都沒有?