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 c++17.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++?