【发布时间】:2012-04-22 14:21:31
【问题描述】:
我正在编写侵入式共享指针,并且我正在使用 C++11 <atomic> 工具作为引用计数器。以下是我的代码的相关片段:
//...
mutable std::atomic<unsigned> count;
//...
void
SharedObject::addReference() const
{
std::atomic_fetch_add_explicit (&count, 1u,
std::memory_order_consume);
}
void
SharedObject::removeReference() const
{
bool destroy;
destroy = std::atomic_fetch_sub_explicit (&count, 1u,
std::memory_order_consume) == 1;
if (destroy)
delete this;
}
我首先从memory_order_acquire 和memory_order_release 开始,但后来我说服自己memory_order_consume 应该足够好。经过进一步考虑,在我看来,即使memory_order_relaxed 也应该可以工作。
现在的问题是我是否可以使用memory_order_consume 进行操作,或者我可以使用较弱的排序 (memory_order_relaxed) 还是应该使用更严格的排序?
【问题讨论】:
-
由于计数器本质上充当
delete语句的递归锁,我想说addReference中的“获取”和removeReference中的“释放”是正确的顺序.但是你的addReference也应该确保计数器不为零! -
@KerrekSB:在对象首次创建后,在分配给
SharedPtr<>之前,addReference()中的计数器可能为零。获取/释放语义似乎应该始终有效。但是是否可以使用较弱的排序约束?为什么不呢? -
关于零:假设 refcount 为 1。现在线程 1 想要删除对象并调用减法。如果此时线程 2 想要增加线程计数,它将从零递增到一,但线程 1 将继续删除该对象。应该避免这种情况。
-
@KerrekSB:这听起来像是
addReference()/removeReference()不平衡或对SharedPtr实例的不受保护的访问,我认为这是未定义的行为。SharedPtrs 作为成员本身需要受到互斥锁等的保护,与其封闭类的其他成员一样。 -
@KerrekSB "我会说 addReference 中的“获取”" 获取什么版本?
标签: c++ c++11 shared-ptr atomic