2013-07-15 47 views
1

我有一個簡單的線程池實現,使用boost::functionboost::bind將成員函數簽名減少爲void func(void)。然後使用boost::functionint對的隊列,彈出隊列頂部並執行函數(全部包裝在互斥塊中)。Boost ::函數綁定成員函數變爲無效

threadPool->addJob(boost::bind(&Foo::bar, this, arg1, arg2)); 

... 

typedef boost::function<void(void)> func; 
std::queue<std::pair<func, int> > funcQ; 

void ThreadPool::addJob(func f){ 
    funcQ.push(std::make_pair(f, j)); 
} 

if (!funcQ.empty()){ 
    func localFunc = (funcQ.front()).first; 
    ... 
    funcQ.pop(); 
    ... 
    localFunc(); 
} 

然而,經過幾次反覆,這是造成段錯誤,當我調用該函數的()運營商,所以我斷言語句拋出,以確保該函數是調用:

... 
assert(funcQ.front().first); 
func localFunc = (funcQ.front()).first; 
... 

瞧,經過幾次迭代之後斷言行程,表明我的boost::function不可調用。

我首先想到函數數據(來自Foo類)在函數被調用之前已被銷燬,但據我瞭解,boost::function創建了一個數據副本,以無論如何形成閉包。不幸的是,我不知道是什麼原因導致boost::function無法繼續解決問題。我是否會錯誤地綁定成員函數,或者是否存在問題並嘗試調用它?

編輯:我應該提到:Foo分配在堆上,而不是delete d直到線程連接。

+2

'boost :: function'會創建一個你傳遞給它的'this'指針的副本,即它保持一個指向相同地址的指針。它不擁有'* this'的副本。 – juanchopanza

回答

1

std ::隊列不是線程安全的。當你說你正在使用互斥體從隊列中彈出時,我知道你將爲推入隊列做同樣的事情。

此外,你需要照顧Foo的一生。考慮將shared_ptr傳遞給異步函數。 (shared_from_this()取代此)

注意:您可以使用boost :: asio來實現任務調度。 這是一篇非常不錯的文章 http://www.gamedev.net/blog/950/entry-2249317-a-guide-to-getting-started-with-boostasio/

+0

每次在互斥體中訪問隊列時,我都確實在打包。 Foo被分配到堆上,直到線程連接之前,析構函數才被調用。此外,我做了這個嘗試和理解如何使用boost :: function和boost :: bind,但我一定會考慮boost :: asio,謝謝! – Oxonium