2013-04-02 24 views
0

我的代碼從第三方庫調用函數。讓我們來調用這個函數SomeFuncC++併發性,避免多重執行問題的同步設計

void SomeFunc(void (*callBack) (int)); 

正如你可以看到SomeFunc需要一個回調函數參數。一旦調用了SomeFunc,調用線程就會進行,並且庫會在不同的線程上執行回調 - 傳遞不同的狀態碼。

我的要求是調用SomeFunc(又名主線程)應該等到一定的狀態代碼傳遞給回調的線程。到目前爲止,我有這樣的事情

CEvent *pEvt = NULL; 

void myCallBack(int code) { 
    if(code == SOME_MAGIC_NUM) pEvt->SetEvent(); // signal thread waiting for this event obj they can continue 
} 

int main (int argc, char** argv) { 
    pEvt = new CEvent(FALSE, TRUE); 
    SomeFunc(myCallBack); // This doesn't block, main thread will progress to next line 
    WaitForSingleObject(pEvt, 5000); // wait here until 3rd party library call myCallBack with code SOME_MAGIC_NUM -- or if it doesn't after 5 seconds, continue 

    // do interesting stuff here.. 

    return EXIT_SUCCESS; 
} 

現在,這似乎很好,如果我只能這樣做像上述主線程/ main函數。但是,如果多個線程可以執行上面主要的代碼塊,我的問題是他們將共享對全局變量pEvt的引用,它會搞砸

什麼是最好的代碼設計方法,我應該在這裏?理想情況下,我想更改回調函數簽名以接受對CEvent對象的引用,但由於它是第三方庫,我無法做到這一點。

+0

這所呈現不明確:是'SomeFunc()'產卵您的輔助線程,然後返回返回到它的調用者(在這種情況下,'主()')?我只問,因爲你在多線程環境中提出了這個問題,然後繼續顯示沒有多線程的代碼。 – WhozCraig

+0

正確,SomeFunc()產生了輔助線程 - 我們稱之爲「線程X」。並從線程X它將調用myCallBack傳遞它不同的代碼參數。主線程和線程X將同時執行,這就是爲什麼我使用上面的'WaitForSingleObject(pEvt,5000)'來暫停主線程,直到我很高興進展 – gerrytan

+0

請問爲什麼你需要多線程來監視單一回調事件? – jwalk

回答

0

只能達到這是第三方提供的方式傳回一個「自定義」的說法回調。精心設計的API允許設置一個回調一個void *值,並且回調在調用時收到這個參數。從這個void *你可以擴展到任何你喜歡的東西,包括對象和方法調用,通過不安全的轉換。所有基於綁定或成員函數地址或任何其他解決方案的解決方案最終歸結爲相同的問題:以某種方式,this*必須傳遞迴回調。

例如,請參閱BIO_set_callback:它允許您設置回調的回調任意參數。注意,callabck參數可以是間接,例如像在GNUTLS:參數可以通過gnutls_session_set_ptr,然後在回調(多個)它可以使用gnutls_session_get_ptr檢索設定爲在會話的任意數據。您的第三方可能會提供這種間接方法。

如果庫不提供這樣的功能,那麼你就擱淺到黑客。例如,您可以收集「可用」回調,每個回調都與特定事件相關聯(即不同作爲地址,儘管代碼相同)。您選擇一個回調並將其從收集中移除並放置,然後等待回撥相關的事件。完成後,將回調放回可用列表中。 「可用」列表的大小在編譯時很難處理,因爲您確實需要單獨的函數,每個函數都有一個函數。

+0

不正確。這是綁定的目的。 – hifier

+0

@hifier:祈禱告訴綁定如何接收隱藏的'this *'參數? –

+0

[像這樣](http://www.boost.org/doc/libs/1_53_0/libs/bind/bind.html#with_member_pointers)。 – hifier