2011-05-04 71 views
7

pthread函數採用void *參數。一個普通的結構,而不是一個指針如何發送?將普通數據傳遞給pthread void *

我想發送一個非指針結構到一個pthread函數。

另外我想發送一個指向void *函數的指針,這是如何完成的?可以將任何指針發送給void *函數嗎?

+0

要傳遞一個結構體,你需要傳遞它的地址(將它轉換爲一個指針)。但是,您需要確保該對象不會被破壞(因爲該線程將引用該對象)。 是的,你可以將任何指針傳遞給void * – forsvarir 2011-05-04 10:01:54

+0

你不能(AFAIK)。指向基於堆的struct的指針有什麼問題? – 2011-05-04 10:02:12

+0

我可以不只是像這樣的&thestruct發送結構到(void *) – jarryd 2011-05-04 10:04:32

回答

7

不可能;你必須發送一個指針。然而,void *可以指向任何東西。如果你的struct變量被調用foo,你可以簡單地將它作爲(void *) &foo傳遞,並且在函數內部,你可以將它轉換回例如struct Foostruct Foo * fooPtr = (struct Foo *) param;struct Foo foo = *((struct Foo *) param);

編輯:作爲@forsvarir在評論中提到,foo一定不是是一個局部變量(除非調用函數等待線程完成)。請參閱@Gavin Lock的文章。

3

如前所述,您必須傳遞一個指針。把void *想象成一個無類型的指針,所以你必須把它轉換回你的線程函數中正確的類型。 (請參閱Aasmund的答案)

正如forsvarir提到的,您必須確保指向的結構在線程使用之前不被銷燬 - 最安全的方法是在堆上新建結構並傳遞其地址並擁有線程功能。

我的意思是「傳遞所有權」那是什麼的函數,消息結構不得刪除它,線程函數必須刪除結構一旦用它做。

+0

+1有關所有權的觀點。 – 2011-05-04 10:14:21

7

根據您的意見,你需要做這樣的事情......

在主代碼:

void PassSomeStuff(struct TheStruct myStruct) { 
    struct TheStruct *pStruct = malloc(sizeof(struct TheStruct)); 
    memcpy(pStruct, &myStruct, sizeof(struct TheStruct)); 

    /* Start the watchdog thread passing in the structure */ 
    pthread_create(/* other args */, &myWatchDogThreadFunc, pStruct); */ 
} 

在你的看門狗線程:

void *myWatchDogThreadFunc(void *pArgs) { 
    struct TheStruct *pStruct = (struct TheStruct *)pArgs; 

    /* use the struct */ 

    /* Pass Ownership to the navigation thread*/ 
    /* Start the navigation thread passing in the structure */ 
    pthread_create(/* other args */, &myNavigationThreadFunc, pStruct); 
} 

在您的導航線:

void *myNavigationThreadFunc(void *pArgs) { 
    struct TheStruct *pStruct = (struct TheStruct *)pArgs; 
    /* use the struct */ 

    /* cleanup */ 
    free(pStruct); /* or pass it to somebody else... */ 
} 

你不能只是做:

void PassSomeStuff(struct TheStruct myStruct) { 
    pthread_create(/* other args */, &myStruct); 
} 

因爲myStruct將得到清理...當PassSomeStuff回報。獲取地址(獲取指針)不會複製對象。

注:

  • 您的任何線程可以通過撥打免費清理結構,只要你確信所有線程都在使用它完成的。
  • 所有的線程(主,看門狗,導航)都指向同一個結構實例(所以如果他們改變它的內容,你可能需要通過鎖定來保護它)。如果這不是所需的效果,那麼您需要在每一步創建(malloc)結構的新副本,以便每個線程都擁有它自己的值副本。
+0

+1用於編寫代碼示例。 – JeremyP 2011-05-04 10:55:27

+0

我要從一開始就傳遞一個指針。 malloc,然後將它發送到看門狗(也是一個線程),然後看門狗必須將它傳遞給gps導航線程。我可以直接沿着void * pthread args傳遞指針嗎? – jarryd 2011-05-04 11:40:12

+0

@ Helium3:我已更新我的帖子以反映我的想法,包括底部的一些筆記。簡短的答案是肯定的(假設我已經正確理解了你)。 – forsvarir 2011-05-04 12:43:46

1

這不是一個完整的答案,而是另一種解決方案,以警告其他人提供的有關確保新線程獲得結構時仍然存在的警告。當然你可以用malloc來獲得它,並給新線程負責free。在許多方面,這似乎是最簡單和最便宜的方式(不需要同步),但同步實際上隱藏在mallocfree之內,並且可能會稍微昂貴,尤其是因爲大多數面向線程的分配器(例如ptmalloc和tcmalloc)會產生額外的當釋放內存的線程與分配內存的線程不一樣時的成本。

,你可以使用不同的方法是把一個並行線程屏障在你的初始化結構內,並在其上等待:

pthread_barrier_init(&init_struct.barrier, 0, 2); 
pthread_create(&td, 0, start_func, &init_struct); 
pthread_barrier_wait(&init_struct.barrier); 

而且具有線程啓動功能也呼籲pthread_barrier_wait(arg->barrier);的結構複製到它自己的自動後存儲。