2010-07-01 84 views
6

時,我有一個小包裝,其集中有什麼相對於螺紋:「稱爲純虛方法」實現一個boost ::線程封裝接口

class Thread { 
protected: 
    boost::thread *m_thread; 

    virtual void work() = 0; 

    void do_work() { 
     work(); 
    } 

public: 
    Thread() : m_thread(NULL) {} 
    virtual ~Thread() { 
     catch_up(); 
     delete m_thread; 
    } 

    inline void catch_up() { 
     if(m_thread != NULL) { 
      m_thread->join(); 
     } 
    } 

    void run() { 
     m_thread = new boost::thread(boost::bind(&Thread::do_work, boost::ref(*this))); 
    } 
}; 

當我實現它,說有以下幾點:

class A : public Thread { 
    void work() {} 
}; 

在:

A a; a.run(); 

我買了一個漂亮的運行時終止「純虛方法被稱爲」顯示終端ayed。我認爲這是boost :: bind參數,但我不知道怎麼說「使用虛擬純實現」...

先謝謝了。

問候,

先生空軍終於

回答

6

你崩潰發生,只有當你的程序立即退出:它調用A類的析構函數這完成並調用線程的析構函數新啓動的線程必須調度的機會。線程然後調用你的虛函數,但A類不再存在,所以它試圖調用Thread的do_work(),它調用純虛函數()。這裏的額外輸出程序:

run() started 
run() ended 
~A() started 
~A() ended 
~Thread() started 
catch_up() started 
do_work() started 
pure virtual method called 

標準的角度來看,我認爲這是不確定的行爲,因爲對象的生命週期已經結束(析構函數調用開始)時,它的一個引用(boost::ref(*this))來調用do_work( )從線程。

解決方案:讓你破壞你的對象之前,你的線程中執行:

A a; a.run(); 
a.catch_up(); 

或者,作爲boost.thread文檔中說,"the user of Boost.Thread must ensure that the referred-to object outlives the newly-created thread of execution."

+0

嗯,那很簡單...謝謝你,你明確表示了。但是現在我遇到了一個更大的問題(顯然是隨機布爾)......我認爲調試起來會更困難。我只是不應該在這裏使用我的「小丑」,否則我會覺得有需要^^' – 2010-07-01 22:50:00

1

我要出去就在這裏冒險,但我懷疑問題是與你的線程析構函數:

virtual ~Thread() { 
    catch_up(); 
    delete m_thread; 
} 

如果線程不開始,在析構函數中調用catch_up()將使用Thread的vtable而不是A來啓動boost線程,就像在C++中析構函數一樣,vtable與析構函數的類型範圍相匹配,而不是最大派生的vtable。

+0

我認爲新的分配產生的權利後,線程處理?因此,如果m_thread等於NULL,則檢查catch_up()就足以在析構函數比創建線程更快的情況下保護它。 – 2010-07-01 18:15:42

+0

我指的是Thread的析構函數,而不是boost :: thread的析構函數。 – MSN 2010-07-01 19:47:21

+0

我知道,我也在談論這個。但現在我明白了,我想你也指出了,對於誤解,抱歉,我的不好;) – 2010-07-01 22:52:20