2017-10-12 13 views
6

Vì vậy, tôi có một đơn giản cow_ptr. Nó trông giống như sau:Copy on Write with 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()); 
    } 
}; 

này đảm bảo rằng nó giữ một tổ chức phi const T và đảm bảo nó là unique khi nó .write([&](T&){}) s đến nó.

Việc ngừng sử dụng .unique() dường như cho biết thiết kế này là thiếu sót.

Tôi đoán rằng nếu chúng ta bắt đầu với một cow_ptr<int> ptr với 1 trong chủ đề A, vượt qua nó cho chủ đề B, làm cho nó độc đáo, sửa đổi nó để 2, vượt qua ptr nó trở lại và đọc nó trong chủ đề A chúng tôi đã tạo ra một cuộc đua điều kiện.

Làm cách nào để khắc phục sự cố này? Tôi có thể chỉ cần thêm một rào cản bộ nhớ trong write? Cái nào? Hay là vấn đề cơ bản hơn?

Các triệu chứng ít có khả năng xảy ra trên x86 do tính nhất quán của bộ nhớ x86 vượt quá và vượt quá yêu cầu C++?

Trả lời

0

Tôi nghĩ rằng ý tưởng không chấp này là nó không thể được sử dụng không đúng cách như thế nào nếu bạn có mã như thế này:

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

Có thể là nó sẽ thất bại trong việc deinitialise nếu nó xảy ra để chạy 2 lần đồng thời.

Trong trường hợp cụ thể của bạn tôi thấy không có vấn đề, bởi vì

  1. nếu nó không phải là độc đáo và trở thành duy nhất - đó là không có vấn đề lớn, bạn sẽ chỉ làm cho thêm bản sao
  2. nếu nó là độc đáo và trở nên không duy nhất, sau đó bạn thay đổi và sao chép các ví dụ tương tự trong hai chủ đề khác nhau (mà sẽ là một vấn đề nào)

tôi không nghĩ có bất kỳ vấn đề nào khác với đơn đặt hàng để truy cập vào bộ nhớ từ quầy trong shared_ptr được nguyên tử.

Tôi có thể chỉ cần chuyển sang use_count == 1 có thể với nhận xét thích hợp

Các vấn đề liên quan