我正在编写侵入式共享指针,我正在使用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
),还是应该使用更严格的排序?
答案 0 :(得分:20)
void
SharedObject::addReference() const
{
std::atomic_fetch_add_explicit (&count, 1u, std::memory_order_relaxed);
}
void
SharedObject::removeReference() const
{
if ( std::atomic_fetch_sub_explicit (&count, 1u, std::memory_order_release) == 1 ) {
std::atomic_thread_fence(boost::memory_order_acquire);
delete this;
}
}
您希望使用atomic_thread_fence
,delete
严格地位于fetch_sub
之后。 Reference
来自链接文字的引用:
始终可以使用增加引用计数器 memory_order_relaxed:只能形成对对象的新引用 从现有引用,并从一个引用现有引用 线程到另一个必须已经提供任何所需的同步。
在一个对象中强制执行对对象的任何可能访问非常重要 线程(通过现有引用)在删除之前发生 对象在不同的线程中。这是通过“释放”实现的 删除引用后的操作(通过对对象的任何访问) 这个参考必须明显发生在之前),并且“获得” 删除对象之前的操作。
可以将memory_order_acq_rel用于fetch_sub 操作,但这导致不需要的“获取”操作时 参考计数器尚未达到零并且可能会产生性能 罚。