C ++ 11原子和入侵共享指针引用计数 [英] C++11 atomics and intrusive shared pointer reference count

查看:226
本文介绍了C ++ 11原子和入侵共享指针引用计数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我写入侵入式共享指针,我使用C ++ 11 < atomic> 参考计数器。这里是我的代码的相关片段:

I am writing intrusive shared pointer and I am using C++11 <atomic> facilities for reference counter. Here are the relevant fragments of my code:

//...
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 应该可以工作。

I have started with memory_order_acquire and memory_order_release first but then I convinced myself that memory_order_consume should be good enough. After further deliberation it seems to me that even memory_order_relaxed should work.

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

Now, the question is whether I can use memory_order_consume for the operations or could I use weaker ordering (memory_order_relaxed) or should I use stricter ordering?

推荐答案

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 后面。 参考

You want to use atomic_thread_fence such that the delete is strictly after the fetch_sub. Reference

从链接的文本报价:


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

Increasing the reference counter can always be done with memory_order_relaxed: New references to an object can only be formed from an existing reference, and passing an existing reference from one thread to another must already provide any required synchronization.

重要的是在一个
线程(通过现有引用)中强制执行对对象的任何可能访问,以在不同线程中删除
对象之前发生。这是通过在释放引用之后通过释放
操作来实现的(通过
对该对象的任何访问,该引用必须显然在之前发生),以及在删除对象之前的获取
操作。

It is important to enforce any possible access to the object in one thread (through an existing reference) to happen before deleting the object in a different thread. This is achieved by a "release" operation after dropping a reference (any access to the object through this reference must obviously happened before), and an "acquire" operation before deleting the object.

可以对fetch_sub
操作使用memory_order_acq_rel,但是当
引用计数器执行时会导致不必要的获取操作尚未达到零,可能会强加一次性能
罚金。

It would be possible to use memory_order_acq_rel for the fetch_sub operation, but this results in unneeded "acquire" operations when the reference counter does not yet reach zero and may impose a performance penalty.

这篇关于C ++ 11原子和入侵共享指针引用计数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆