20

我正在编写侵入式共享指针,并且正在使用 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_acquireand memory_order_releasefirst 开始,但后来我说服自己memory_order_consume应该足够好。经过进一步审议,在我看来,甚至memory_order_relaxed应该工作。

现在,问题是我是否可以使用memory_order_consume这些操作,或者我可以使用较弱的排序 ( memory_order_relaxed) 还是应该使用更严格的排序?

4

1 回答 1

22
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. 参考

引用链接文本:

始终可以使用 memory_order_relaxed 增加引用计数器:对对象的新引用只能从现有引用形成,并且将现有引用从一个线程传递到另一个线程必须已经提供任何所需的同步。

在删除另一个线程中的对象之前,强制在一个线程中(通过现有引用)对对象进行任何可能的访问,这一点很重要。这是通过删除引用后的“释放”操作(显然之前必须通过此引用访问对象)和删除对象之前的“获取”操作来实现的。

可以将 memory_order_acq_rel 用于 fetch_sub 操作,但是当引用计数器尚未达到零时,这会导致不需要的“获取”操作,并且可能会造成性能损失。

于 2012-04-22T15:26:57.760 回答