2015-06-26 144 views
1

我的對象創建了一個線程,該線程在其生命週期中修改了對象創建者。問題是,線程在銷燬時不應該調用對象方法。我已經找到了一些解決方案,我想知道這是否是最好的。測試對象是否未被刪除

class A 
{ 
    shared_ptr<int> guard = make_shared<int>(0); 
public: 
    weak_ptr<int> getGuard() { return guard; } 
    void method() {} 
    A() 
    { 
     thread([this] 
     { 
      const auto &guard = getGuard(); 
      while(!guard.expired()) 
       method(); 
     }); 
    } 
}; 
+1

您是否打算分離創建的線程,以便線程不會阻塞'A'的構造函數? –

+0

是的,在現實生活中,線程構造不會阻塞主線程。說實話,新的線程甚至沒有在構造函數中創建。我只是試圖簡化示例。 –

回答

1

如果你想確保當你調用method對象不被破壞,但可以在其他時間被摧毀,則需要保留對象本身的weak_ptr,並在調用方法時鎖定該對象。喜歡的東西:

class A : std::enable_shared_from_this<A> 
{ 
public: 
    void method() {} 
    A() 
    { 
     std::weak_ptr<A> self(shared_from_this()); 
     thread([=self] 
     { 
      while (auto This = self.lock()) 
       This->method(); 
     }).detach(); 
    } 
}; 

這個對象現在只能通過make_shared創造的 - 試圖做到這一點不確定的行爲任何其他方式的結果,並可能會崩潰。

3

while循環,你有沒有保證method而指向的對象guard仍然只存在被稱爲線程安全的方式。原因是另一個線程可能會導致在expired的調用和method的調用之間的對象被破壞。

執行此檢查的安全的方法是試圖推動弱指針的共享指針:

while (true) 
{ 
    shared_ptr<int> sp = getGuard().lock(); 
    if (sp) 
    { 
     method(); 
    } 
    else 
    { 
     return; 
    } 
} 

通過促進弱指針的共享指針,調用代碼參與對象的所有權在撥打method的過程中,確保在調用代碼正在使用它時不會被銷燬。

您也未能加入或分離線程。在你的例子中,它看起來像你想分離它,以便A的構造函數可以在線程完成執行前退出。在這種情況下,你的代碼應該是這樣的:

thread([this] 
{ 
    ... 
}).detach(); 
+0

你的答案的第一部分對我來說非常重要。我忽略了那個線程不安全。指針提升不會有幫助(它指向一個類的成員,而不是一個對象),但是用一些互斥鎖包裝這些行將完成這項工作。 這是一些僞代碼來說明整體想法,無論如何感謝關於detach()的建議。 謝謝! –

+0

這並沒有真正的幫助 - 鎖只會阻止共享的'int'而不是對象的銷燬。所以你仍然可以獲得鎖,然後另一個線程銷燬該對象,然後調用被銷燬對象的方法。你需要爲對象本身保留一個'weak_ptr',並鎖定它。 –

+0

@Chris Dodd你是對的,我沒有正確地思考所有的細節,我更關心while循環檢查。隨意編輯這個答案或留下一個新的,否則我將不得不稍後回來,以確保細節得到補充。 –

相關問題