2012-02-23 45 views
1

如何創建對象的std :: vector,並且每個對象都有一個boost :: thread封裝在裏面。std ::帶有boost :: thread封裝的對象向量insde

class INSTRUMENT { 
public: 
    INSTRUMENT() : m_thread(new boost::thread(&INSTRUMENT::Start, this)) { 
     x = "abc"; 
    } 
    ~INSTRUMENT() {} 
    void Start(); 
public: 
    std::string x; 
    boost::shared_ptr<boost::thread> m_thread; 
}; 

void INSTRUMENT::Start() { 
    try { 
     while (1) { 
      boost::this_thread::interruption_point(); 
      std::cout << "here " << x << std::endl; 
     } 
    } catch (boost::thread_interrupted &thread_e) { 
     std::cout << "exit " << x << std::endl; 
    } catch (std::exception &e) { 
    } 
} 

std::vector<INSTRUMENT> m_inst_vector; 

for (int i = 0; i < 5; i++) { 
    m_inst_vector.push_back(INSTRUMENT()); 
} 

該代碼編譯得很好,但輸出只是一些垃圾,不像預期的「abc」。在調試中,我注意到每次調用.push_back()時都會調用〜INSTRUMENT()。

由於當前設計的限制,我嘗試不使用boost :: group_thread。只是想知道是否有可能有一個線程內的對象的std ::向量,或任何建議類似的設計將是非常有益的。

我在SO上找到類似的線程。它提到了編譯器支持的移動語義,但沒有解釋它是什麼。 How can I add boost threads to a vector

謝謝。

+0

編輯我的答案。 – vz0 2012-02-23 05:10:12

回答

3

該代碼有兩個問題。首先,線程立即開始運行boost::thread對象被構造,因此您需要確保它所訪問的任何數據都被預先初始化 - 即在構建線程之前在成員初始化列表中初始化x

其次,線程使用INSTRUMENT對象的this指針,因此您的對象綁定到特定地址。 std::vector複製值:當您調用push_back時,它將對象複製到向量中,並且如果必須分配新的內存塊以騰出空間,則添加其他元素可能會複製其他元素。這是你看到的析構函數調用的原因:臨時構造,push_back將其複製到向量,然後臨時被破壞。

要解決這個問題,您需要確保一旦構建您的INSTRUMENT對象不能被移動或複製,因爲副本具有錯誤的語義。通過使您的副本構造函數和賦值運算符保持私有和未實現(或者如果您擁有支持此新C++ 11構造的最新編譯器將其標記爲已刪除),或者從boost::noncopyable派生。完成此操作後,您不再需要線程的shared_ptr,因爲它不能共享,所以您可以直接構建它。

如果INSTRUMENT不可複製,則不能將其直接存儲在向量中,因此請在向量中使用類似boost::shared_ptr<INSTRUMENT>之類的東西。這將允許矢量自由地複製和重新組合它的元素,而不會影響對象的地址,並確保它在最後被正確銷燬。

class INSTRUMENT: boost::noncopyable { 
public: 
    INSTRUMENT() : x("abc"),m_thread(&INSTRUMENT::Start, this) { 
    } 
    ~INSTRUMENT() {} 
    void Start(); 
public: 
    std::string x; 
    boost::thread m_thread; 
}; 

void INSTRUMENT::Start() { 
    try { 
     while (1) { 
      boost::this_thread::interruption_point(); 
      std::cout << "here " << x << std::endl; 
     } 
    } catch (boost::thread_interrupted &thread_e) { 
     std::cout << "exit " << x << std::endl; 
    } catch (std::exception &e) { 
    } 
} 

std::vector<boost::shared_ptr<INSTRUMENT> > m_inst_vector; 

for (int i = 0; i < 5; i++) { 
    m_inst_vector.push_back(boost::shared_ptr<INSTRUMENT>(new INSTRUMENT)); 
} 
+0

謝謝安東尼。你的代碼正是我一直在尋找的,它的工作原理是100%。 – 2607 2012-02-23 17:25:34

0

編輯:您的代碼中存在爭用條件。該線程在x獲得初始化之前啓動。

您應該將載體更改爲vector<boost::shared_ptr<INSTRUMENT> >,並從INSTRUMENT中刪除boost::shared_ptr

class INSTRUMENT { 
public: 
    INSTRUMENT() { 
     x = "abc"; 
     m_thread = boost::thread(&INSTRUMENT::Start, this) 
    } 
    ~INSTRUMENT() {} 
    void Start(); 
public: 
    std::string x; 
    boost::thread m_thread; 
}; 

for (int i = 0; i < 5; i++) { 
    m_inst_vector.push_back(boost::shared_ptr<INSTRUMENT>(new INSTRUMENT())); 
} 
+0

感謝您的回覆,我仍然遇到同樣的問題,在調用.push_back()後調用INSTRUMENT()。 m_inst_vector。push_back(boost :: shared_ptr (new Test())); – 2607 2012-02-23 05:25:41