2017-10-12 71 views
6

所以我有一個簡單的cow_ptr。它看起來是這樣的:使用shared_ptr寫複製

template<class T, class Base=std::shared_ptr<T const>> 
struct cow_ptr:private Base{ 
    using Base::operator*; 
    using Base::operator->; 
    using Base::operator bool; 
    // etc 

    cow_ptr(std::shared_ptr<T> ptr):Base(ptr){} 

    // defaulted special member functions 

    template<class F> 
    decltype(auto) write(F&& f){ 
    if (!unique()) self_clone(); 
    Assert(unique()); 
    return std::forward<F>(f)(const_cast<T&>(**this)); 
    } 
private: 
    void self_clone(){ 
    if (!*this) return; 
    *this = std::make_shared<T>(**this); 
    Assert(unique()); 
    } 
}; 

這樣可以保證它擁有一個非const T,並確保它是unique.write([&](T&){}) s到它。

棄用.unique()似乎表明此設計存在缺陷。

我猜測,如果我們開始與在線程A 1一個cow_ptr<int> ptr,它傳遞給線程B,使其具有唯一性,其修改爲2,通過ptr回讀它的線程A,我們已經產生了種族條件。

我該如何解決這個問題?我可以簡單地在write中添加內存障礙嗎?哪一個?還是這個問題更根本?

由於x86內存一致性超出了C++的要求,x86上的症狀可能性較低嗎?

回答

0

我想棄用此的想法是,它不能被使用不當一樣,如果你有這樣的代碼:

if(sp.unique()) { 
    // some deinitialisation 
} else { 
    // somebody else will deinitialise. 
} 

這是可能的,它會失敗deinitialise如果它發生運行同時2次。

在我看不出有什麼問題,你的具體情況,因爲

  1. ,如果它不是唯一的,併成爲獨特的 - 這沒什麼大不了的,你只會讓額外的複製
  2. ,如果它是獨一無二的,變得不是唯一的,那麼你改變並複製在兩個不同的線程相同的實例(這將是反正有問題)

我不認爲有任何其他問題,用命令來訪問內存,因爲櫃檯shared_ptr被原子。

我可能只是切換到use_count == 1可能會有適當的評論