2016-02-13 39 views
0

我已經挖掘了各種書籍和在線資源,但仍然不確定如何處理這種情況一個不斷循環的成員函數可能會啓動一個可能需要訪問其他成員函數和變量的新線程(並且有時會對它們進行變異)。下面的代碼描述的情況:在成員函數中正確捕獲(lambda)和安全問題開始一個新的線程(C++ 11/14)

class Foo { 
    int read_only; 
    Object some_big_object; 
    std::atomic<int> read_and_write; 
    // more private member variables 
    void helper_function_a(const Object& value) { 
    Object copy = value.clone(); // deep copy 
    std::thread t {[/*what should I put here?*/](){ 
    // read from read_only and WRITE to read_and_write 
    if (/*some condition which is occasionally true*/) 
     helper_function_b(copy); 
     }}; 
    t.detach(); 
    } 
    void helper_function_b(const Object& value) { 
    // change value 
    } 
public: 
    void update() { 
    // update some_big_object; 
    // read from read_only and READ OR WRITE from/to read_and_write 
    helper_function_a(some_big_object); 
    } 
    void doSomething; 
}; 

int main() { 
    Foo f; 
    while (true) { 
    f.update(); 
    } 
} 

我知道,我可以把this成員函數中捕捉到的一切,但我真的不希望捕捉到一切,只是我用,如果有可能的事情,沒有其他的。我真正的類更復雜,也具有應該保持不變的變量,但我不能聲明const(因爲我在構造函數的主體中初始化了它們) - 確保lambda只能訪問它使用的東西。那麼我應該在那裏放什麼?

那麼這個設計呢?感覺不對 - 但是它?爲什麼?請注意,在我真正的課程(這是更復雜)helper_function_a失敗 - 我仍然不確定錯誤的確切位置,但如果我刪除lambda並使其單線程它可以工作。在我的應用程序中,我使用helper_function_a在更新動畫時執行大對象的文件IO - 它不覺得寫入來執行來自同一線程的兩個任務。

最後,我可以安全使用read_and_write嗎?

+2

如果要使用類的成員,您必須捕獲'this',那麼真的沒有辦法繞過它。 –

+0

你的代碼調用'helper_function_b(...)'(一種方法)...並且你不想捕獲'this'? – 6502

+0

我一直在想''(this-> helper_function_b)'(當然不會編譯)。但是你的意見使得它相當明確,沒有辦法解決它.. –

回答

1

如果您在lambda內使用成員函數,那麼您應該捕獲this。 您還應該考慮this的生命期和helper_function_a中創建的線程。 我可能會建議你使用某種類型的線程池的Foo對象內,等待/中斷所有的線程在析構函數

如果你不想捕捉this您可以嘗試移動helper_function_b(與helper_function_b所有使用數據)的Foo一些成員和捕獲成員(不要忘記它的壽命)

如果您需要const成員長初始化您可以使用函數來創建它們:

Foo::Foo(args ...): 
    member(build_member(args ...)), 
    ... 
{}; 

另一種方式控制生命週期是使用共享指針和std :: enable_shared_from_this,如this示例

+0

和'build_member'可能會發出一些異常?就像讀一些文件或初始化硬件時一樣? 'build_member'應該是什麼樣的功能?在實現文件的主體中可能有一些靜態的免費函數?或者更好一些匿名'命名空間'? –

+0

您可能會捕獲並處理在'build_member'中拋出的異常。像[這裏](http://www.gotw.ca/gotw/066.htm)一樣。 'build_member'可以是簡單的自由函數或靜態成員函數。隨你喜歡 –