所以我有一个简单的cow_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&){})
。
.unique()
的{{3}}弃用似乎表明此设计存在缺陷。
我猜测如果我们从线程A中的cow_ptr<int> ptr
1
开始,将其传递给线程B,使其唯一,将其修改为2
,传递{{1它返回并在线程ptr
中读取它我们已经生成了竞争条件。
我该如何解决这个问题?我可以在A
中添加内存屏障吗?哪一个?或问题更为根本?
由于x86内存的一致性超出了C ++的要求,x86上的症状是否会降低?
答案 0 :(得分:0)
我认为弃用此功能的想法是不能错误地使用它,就像你有这样的代码一样:
if(sp.unique()) {
// some deinitialisation
} else {
// somebody else will deinitialise.
}
如果碰巧同时运行2次,它可能无法取消初始化。
在您的特定情况下,我认为没有问题,因为
我认为订单访问内存没有任何其他问题,因为shared_ptr
中的计数器是原子的。
我可能只是切换到use_count == 1
可能会有适当的评论