Ric*_*erd 6 c++ atomic shared-ptr c++11
我想std::atomic<std::shared_ptr>在我的代码中使用a ,以便shared_ptr可以原子地更新,但是在访问shared_ptr时我遇到了问题.原子上的load()方法似乎减少了shared_ptr上的ref-count,因此我不能在不释放它的情况下实际使用该对象.
这是一段显示问题的简化代码......
typedef shared_ptr<MyClass> MyClassPtr;
typedef atomic<MyClassPtr> MyClassAtomicPtr;
// 1.
MyClassPtr ptr( new MyClass() );
printf("1. use_count=%d\n", ptr.use_count());
// 2.
MyClassAtomicPtr atomicPointer(ptr);
printf("2. use_count=%d\n", ptr.use_count());
// 3.
{
MyClassPtr p = atomicPointer.load();
printf("3a. use_count=%d\n", ptr.use_count());
}
printf("3b. use_count=%d\n", ptr.use_count());
// 4.
{
MyClassPtr p = atomicPointer.load();
printf("4a. use_count=%d\n", ptr.use_count());
}
printf("4b. use_count=%d\n", ptr.use_count());
Run Code Online (Sandbox Code Playgroud)
这个输出是:
1. use_count=1
2. use_count=2
3a. use_count=2
3b. use_count=1
4a. use_count=1
4b. use_count=-572662307
Run Code Online (Sandbox Code Playgroud)
我理解第1步和第2步.但是在第3步,我希望对shared_ptr的赋值可以将ref-count增加到3,然后当它超出ref-count范围时返回到2.事实上,当分配时它保持在2,然后当shared_ptr超出范围时减少到1.类似地,在步骤4中,ref-count变为零并且删除对象.
所以我的问题是:如何在不破坏原子的情况下访问和使用原子管理的shared_ptr?
(我正在使用Visual Studio 2012版本11.0.50727.1 RTMREL进行编译)
您不能将其std::shared_ptr<T>用作模板参数类型std::atomic<T>."模板参数T的类型应该是可以轻易复制的." (N3290中的§29.51)std::shared_ptr<T>不是轻易复制的.
显然,在您的示例std::memcpy(或类似的东西)中用于复制std::shared_ptr,之后调用析构函数.这就是递减引用计数的原因.在最后一步中,删除该对象.
解决方案是使用a std::mutex来保护你的std::shared_ptr.
我相信原子加载和存储共享指针的标准方法是使用§20.7.2.5[util.smartptr.shared.atomic]中的函数.似乎只有clac的libc ++支持它们:
template<class T> bool atomic_is_lock_free(const shared_ptr<T>* p);
template<class T> shared_ptr<T> atomic_load(const shared_ptr<T>* p);
template<class T> shared_ptr<T> atomic_load_explicit(const shared_ptr<T>* p, memory_order mo);
template<class T> void atomic_store(shared_ptr<T>* p, shared_ptr<T> r);
template<class T> void atomic_store_explicit(shared_ptr<T>* p, shared_ptr<T> r, memory_order mo);
template<class T> shared_ptr<T> atomic_exchange(shared_ptr<T>* p, shared_ptr<T> r);
template<class T> shared_ptr<T> atomic_exchange_explicit(shared_ptr<T>* p, shared_ptr<T> r, memory_order mo);
template<class T> bool atomic_compare_exchange_weak(shared_ptr<T>* p, shared_ptr<T>* v, shared_ptr<T> w);
template<class T> bool atomic_compare_exchange_strong(shared_ptr<T>* p, shared_ptr<T>* v, shared_ptr<T> w);
template<class T> bool atomic_compare_exchange_weak_explicit(shared_ptr<T>* p, shared_ptr<T>* v, shared_ptr<T> w, memory_order success, memory_order failure);
template<class T> bool atomic_compare_exchange_strong_explicit(shared_ptr<T>* p, shared_ptr<T>* v, shared_ptr<T> w, memory_order success, memory_order failure);
Run Code Online (Sandbox Code Playgroud)
所以你的代码可以写成:
auto ptr = std::make_shared<MyClass>();
printf("1. use_count=%d\n", ptr.use_count());
{
auto p = std::atomic_load(&ptr);
printf("3a. use_count=%d\n", ptr.use_count());
}
printf("3b. use_count=%d\n", ptr.use_count());
{
auto p = std::atomic_load(&ptr);
printf("3a. use_count=%d\n", ptr.use_count());
}
printf("4b. use_count=%d\n", ptr.use_count());
Run Code Online (Sandbox Code Playgroud)
但是我无法在MSDN上找到这样的支持,所以你能做的最好就是使用互斥锁.(实际上,libc ++中这些函数的实现也使用了互斥锁.)
| 归档时间: |
|
| 查看次数: |
2903 次 |
| 最近记录: |