2017-06-27 220 views
4

我目前正在開發一個項目,其中我們有一個C線程實現,用於使用pthreads的UNIX系統。現在我們希望能夠在Windows上運行整個項目,並且我正在翻譯WIN32的所有線程。現在我遇到了一個問題,我無法提出一個體面的解決方案。CreateThread包裝函數

我有thrd_create()功能:

static inline int thrd_create(thrd_t *thr, thrd_start_t func, void *arg) { 
    Args* args = malloc(sizeof(Args)); 
    args->arg = arg; 
    args->function = func; 
    *thr = CreateThread(NULL, 0, wrapper_function, (LPVOID) args, 0, NULL); 
    if (!*thr) { 
     free (args); 
     return thrd_error; 
    } 
    return thrd_success; 
} 

此功能是爲了建立一個新的線程,並且用戶提供了一個啓動功能。爲了方便起見,如果可能,我想離開調用thrd_create()的實現。出於這個原因,我創建了一個:

static inline DWORD wrapper_function(LPVOID arg) { 
    Args * args; 
    args = (Args*) arg; 
    DWORD res = args->function(args->arg); //This does obviously not work 
    return res; 
} 

我的問題是:什麼DWORD應我的包裝功能的回報?用戶爲pthread實現提供的函數具有void返回類型,所以我不會從中得到任何結果。有什麼建議麼?

編輯

參數數量看起來是這樣的:

struct Args { 
    void (*function)(void * aArg); 
    void* arg; 
}; 
typedef struct Args Args; 
+0

什麼是'Args'? –

+7

爲什麼不只是返回零? Windows返回的值實際上並未被使用。是不是類似於你已經有了與pthreads(因爲pthreads線程函數返回一個'void *')? –

+0

@Someprogrammerdude我想你剛剛粉碎了我和解決方案之間的牆。你是對的,如果有的話,返回值將是用戶的興趣。用戶是......我。 – PKlumpp

回答

0

根據手冊它是更好地堅持一個正確的簽名,並使用返回值:

  1. Windows
  2. Pthreads

另一個值得關注的問題是args的生命週期,我認爲最好的方法是讓調用者清理,因此他們需要跟蹤線程直到它終止。

近似的API可以沿着以下線的東西:

/* Your general error codes enumeration 
* which should probably reside in a general 
* header 
*/ 
typedef enum { 
    OK = 0, 
    // Your application specific error codes 
} error_t; 

#ifdef _WIN32 
    #include <Windows.h> 
    typedef HANDLE thread_handle_t; 
#else // assume pthreads 
    #include <pthread.h> 
    typedef pthread_t thread_handle_t; 
#endif 

typedef error_t(*entry_func_t)(void*); 

typedef struct { 
    entry_func_t  func; 
    void    *args; 
    error_t   _result; 
    thread_handle_t _handle; 
} thread_t; 

// returns OK(0) on success 
// returns error code indicating a problem 
error_t thread_create(thread_t *t); 

的aproximate實現是:

#ifdef _WIN32 
    DWORD _win_entry_f(void *args) { 
    thread_t *t = args; 
    t->_result = t->func(t->args); 
    return 0; // Or some other Windows-specific value 
    } 

    error_t thread_create(thread_t *t) { 
    error_t err = OK; 
    if(!(t->_handle = ThreadCreate(NULL, 0, _win_entry_f, t, 0, NULL))) { 
     switch (GetLastError()) { 
     // Populate error with code 
     } 
    } 
    return err; 
    } 
#else 
    void * _pthread_entry_f(void *args) { 
    thread_t *t = args; 
    t->_result = t->func(t->args); 
    return NULL; // Or some other pthreads specific value 
    } 

    error_t thread_create(thread_t *t, entry_func_t func, void *args) { 
    error_t err = OK; 
    switch(pthread_create(&t->_handle, NULL, _pthread_entry_f, t)) { 
    case 0: break; 
    // other cases populate err 
    } 
    return err; 
    } 
#endif 

Invokation看起來有點像這樣。

error_t func(void* args) { 
    return OK; 
} 

..................... 

thread_t t = { .func = func, .args = NULL }; 
thread_create(&t); 

顯然,你需要實現自己的取消,導致收集,加盟,...